[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: How does clk gated work?



Hi,

We made the changes you suggested but it still doesn't work as we think it
should. We want the clock to run only when we have written data to the
transmit register (a 32 bit transfer)

Here is the source to give you a better understanding:
--------------------
#define VS1001K_MAJOR 240
#define DEFAULT_FRAME_RATE 0
#define DEFAULT_WORD_RATE 31

static int __init vs1001k_init(void)
{
        if (register_chrdev(VS1001K_MAJOR,"vs1001k mp3 decoder", &vs1001k_fops) <0 )
        {
                printk("unable to get major for vs1001k driver\n");
                return -EBUSY;
        }
        /* deselect sync ports */
        SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);
        SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);
        SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, ser3, select);
        *R_GEN_CONFIG_II = gen_config_ii_shadow;

        SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser1, ss1extra);
        *R_PORT_PB_I2C = port_pb_i2c_shadow;
        SETS(port_pb_dir_shadow, R_PORT_PB_DIR, dir7, output);
        SETS(port_pb_dir_shadow, R_PORT_PB_DIR, dir6, output);
        SETS(port_pb_dir_shadow, R_PORT_PB_DIR, dir5, input);
        *R_PORT_PB_DIR = port_pb_dir_shadow;

        *R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow = (
          IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec)         |
          IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u1, external) |
          IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec)         |
          IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u3, external) |
          IO_STATE(R_SYNC_SERIAL_PRESCALE, prescaler, div4)           |
          IO_STATE(R_SYNC_SERIAL_PRESCALE, warp_mode, normal)         |
          IO_FIELD(R_SYNC_SERIAL_PRESCALE, frame_rate, DEFAULT_FRAME_RATE)|
          IO_FIELD(R_SYNC_SERIAL_PRESCALE, word_rate, DEFAULT_WORD_RATE));

        *R_SYNC_SERIAL1_CTRL = sync_ctrl_data_shadow =
          IO_STATE(R_SYNC_SERIAL1_CTRL, tr_baud, c115k2Hz)      |
          IO_STATE(R_SYNC_SERIAL1_CTRL, dma_enable, off)        |
          IO_STATE(R_SYNC_SERIAL1_CTRL, mode, master_output)    |
          IO_STATE(R_SYNC_SERIAL1_CTRL, error, normal)          |
          IO_STATE(R_SYNC_SERIAL1_CTRL, rec_enable, disable)    |
          IO_STATE(R_SYNC_SERIAL1_CTRL, f_synctype, normal)     |
          IO_STATE(R_SYNC_SERIAL1_CTRL, f_syncsize, bit)        |

          IO_STATE(R_SYNC_SERIAL1_CTRL, f_sync, on)             |
          IO_STATE(R_SYNC_SERIAL1_CTRL, clk_mode, gated)        |
          IO_STATE(R_SYNC_SERIAL1_CTRL, clk_halt, stopped)      |
          IO_STATE(R_SYNC_SERIAL1_CTRL, bitorder, msb)          |
          IO_STATE(R_SYNC_SERIAL1_CTRL, tr_enable, disable)     |
          IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit)    |
          IO_STATE(R_SYNC_SERIAL1_CTRL, buf_empty, lmt_8)       |
          IO_STATE(R_SYNC_SERIAL1_CTRL, buf_full, lmt_8)        |
          IO_STATE(R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled)    |
          IO_STATE(R_SYNC_SERIAL1_CTRL, clk_polarity, neg)      |
          IO_STATE(R_SYNC_SERIAL1_CTRL, frame_polarity, normal) |
          IO_STATE(R_SYNC_SERIAL1_CTRL, status_polarity, normal)|
          IO_STATE(R_SYNC_SERIAL1_CTRL, clk_driver, inverted)   |
          IO_STATE(R_SYNC_SERIAL1_CTRL, frame_driver, normal)   |
          IO_STATE(R_SYNC_SERIAL1_CTRL, status_driver, normal)  |
          IO_STATE(R_SYNC_SERIAL1_CTRL, def_out0, low);


        /* select sync ports */
        SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);
        *R_GEN_CONFIG_II = gen_config_ii_shadow;
        printk("vs1001k driver\n");
        return 0;
}

static int vs1001k_open(struct inode *inode, struct file *file)
{
        if (vs1001k.in_use == 1)
        {
                DEBUG(printk("Device is busy.. \n"));
                return -EBUSY;
        }
        vs1001k.in_use = 1;

        SETS(sync_ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, running);
        SETS(sync_ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, enable);

        *R_SYNC_SERIAL1_CTRL = sync_ctrl_data_shadow;

        return 0;
}

static int vs1001k_release(struct inode *inode, struct file *file)
{
        SETS(sync_ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, stopped);
        SETS(sync_ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, disable);
        //SETS(sync_ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, disable);
        *R_SYNC_SERIAL1_CTRL = sync_ctrl_data_shadow;
        vs1001k.in_use = 0;
        return 0;
}

static ssize_t vs1001k_write(struct file * file, const char * buf,
                                 size_t count, loff_t *ppos)
{
        unsigned dummy;

        copy_from_user(vs1001k.out_buffer, buf, count);

        dummy = *R_SYNC_SERIAL1_STATUS;

        *R_SYNC_SERIAL1_TR_DATA = (unsigned)0xa0ff00b0;

        udelay(100);
        return count;
}

module_init(vs1001k_init);
----------------------



Thanks for your fast replies!

We hope you will find something seriously wrong with what we are doing ;-)

Regards,
Anders & Björn

On Thu, 25 Apr 2002, Mikael Starvik wrote:
> I think that the problem is that you set error to ignore. With
> error set to igonre the synchronous serial port continues to
> tranmsit data even if there is no data available for transmission.
>