Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af818471 authored by Kristoffer Nyborg Gregertsen's avatar Kristoffer Nyborg Gregertsen Committed by Haavard Skinnemoen
Browse files

[AVR32] SMC configuration in clock cycles



This patch makes the SMC configuration take timings in clock cycles
instead of nanoseconds. A function to calculate timings in clock
cycles is added.

This patch removes the rounding troubles of the previous SMC
configuration method.

[hskinnemoen@atmel.com: fix atstk1002/atngw100 flash config]
Signed-off-by: default avatarKristoffer Nyborg Gregertsen <gregerts@stud.ntnu.no>
Signed-off-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent 193fdd1a
Loading
Loading
Loading
Loading
+4 −1
Original line number Original line Diff line number Diff line
@@ -15,7 +15,7 @@


#include <asm/arch/smc.h>
#include <asm/arch/smc.h>


static struct smc_config flash_config __initdata = {
static struct smc_timing flash_timing __initdata = {
	.ncs_read_setup		= 0,
	.ncs_read_setup		= 0,
	.nrd_setup		= 40,
	.nrd_setup		= 40,
	.ncs_write_setup	= 0,
	.ncs_write_setup	= 0,
@@ -28,7 +28,9 @@ static struct smc_config flash_config __initdata = {


	.read_cycle		= 120,
	.read_cycle		= 120,
	.write_cycle		= 120,
	.write_cycle		= 120,
};


static struct smc_config flash_config __initdata = {
	.bus_width		= 2,
	.bus_width		= 2,
	.nrd_controlled		= 1,
	.nrd_controlled		= 1,
	.nwe_controlled		= 1,
	.nwe_controlled		= 1,
@@ -82,6 +84,7 @@ static int __init atngw100_flash_init(void)
{
{
	int ret;
	int ret;


	smc_set_timing(&flash_config, &flash_timing);
	ret = smc_set_configuration(0, &flash_config);
	ret = smc_set_configuration(0, &flash_config);
	if (ret < 0) {
	if (ret < 0) {
		printk(KERN_ERR "atngw100: failed to set NOR flash timing\n");
		printk(KERN_ERR "atngw100: failed to set NOR flash timing\n");
+4 −1
Original line number Original line Diff line number Diff line
@@ -15,7 +15,7 @@


#include <asm/arch/smc.h>
#include <asm/arch/smc.h>


static struct smc_config flash_config __initdata = {
static struct smc_timing flash_timing __initdata = {
	.ncs_read_setup		= 0,
	.ncs_read_setup		= 0,
	.nrd_setup		= 40,
	.nrd_setup		= 40,
	.ncs_write_setup	= 0,
	.ncs_write_setup	= 0,
@@ -28,7 +28,9 @@ static struct smc_config flash_config __initdata = {


	.read_cycle		= 120,
	.read_cycle		= 120,
	.write_cycle		= 120,
	.write_cycle		= 120,
};


static struct smc_config flash_config __initdata = {
	.bus_width		= 2,
	.bus_width		= 2,
	.nrd_controlled		= 1,
	.nrd_controlled		= 1,
	.nwe_controlled		= 1,
	.nwe_controlled		= 1,
@@ -82,6 +84,7 @@ static int __init atstk1000_flash_init(void)
{
{
	int ret;
	int ret;


	smc_set_timing(&flash_config, &flash_timing);
	ret = smc_set_configuration(0, &flash_config);
	ret = smc_set_configuration(0, &flash_config);
	if (ret < 0) {
	if (ret < 0) {
		printk(KERN_ERR "atstk1000: failed to set NOR flash timing\n");
		printk(KERN_ERR "atstk1000: failed to set NOR flash timing\n");
+112 −17
Original line number Original line Diff line number Diff line
@@ -29,16 +29,25 @@ struct hsmc {


static struct hsmc *hsmc;
static struct hsmc *hsmc;


int smc_set_configuration(int cs, const struct smc_config *config)
void smc_set_timing(struct smc_config *config,
		    const struct smc_timing *timing)
{
{
	int recover;
	int cycle;

	unsigned long mul;
	unsigned long mul;
	unsigned long offset;
	u32 setup, pulse, cycle, mode;


	if (!hsmc)
	/* Reset all SMC timings */
		return -ENODEV;
	config->ncs_read_setup	= 0;
	if (cs >= NR_CHIP_SELECTS)
	config->nrd_setup	= 0;
		return -EINVAL;
	config->ncs_write_setup	= 0;
	config->nwe_setup	= 0;
	config->ncs_read_pulse	= 0;
	config->nrd_pulse	= 0;
	config->ncs_write_pulse	= 0;
	config->nwe_pulse	= 0;
	config->read_cycle	= 0;
	config->write_cycle	= 0;


	/*
	/*
	 * cycles = x / T = x * f
	 * cycles = x / T = x * f
@@ -50,16 +59,102 @@ int smc_set_configuration(int cs, const struct smc_config *config)


#define ns2cyc(x) ((((x) * mul) + 65535) >> 16)
#define ns2cyc(x) ((((x) * mul) + 65535) >> 16)


	setup = (HSMC_BF(NWE_SETUP, ns2cyc(config->nwe_setup))
	if (timing->ncs_read_setup > 0)
		 | HSMC_BF(NCS_WR_SETUP, ns2cyc(config->ncs_write_setup))
		config->ncs_read_setup = ns2cyc(timing->ncs_read_setup);
		 | HSMC_BF(NRD_SETUP, ns2cyc(config->nrd_setup))

		 | HSMC_BF(NCS_RD_SETUP, ns2cyc(config->ncs_read_setup)));
	if (timing->nrd_setup > 0)
	pulse = (HSMC_BF(NWE_PULSE, ns2cyc(config->nwe_pulse))
		config->nrd_setup = ns2cyc(timing->nrd_setup);
		 | HSMC_BF(NCS_WR_PULSE, ns2cyc(config->ncs_write_pulse))

		 | HSMC_BF(NRD_PULSE, ns2cyc(config->nrd_pulse))
	if (timing->ncs_write_setup > 0)
		 | HSMC_BF(NCS_RD_PULSE, ns2cyc(config->ncs_read_pulse)));
		config->ncs_write_setup = ns2cyc(timing->ncs_write_setup);
	cycle = (HSMC_BF(NWE_CYCLE, ns2cyc(config->write_cycle))

		 | HSMC_BF(NRD_CYCLE, ns2cyc(config->read_cycle)));
	if (timing->nwe_setup > 0)
		config->nwe_setup = ns2cyc(timing->nwe_setup);

	if (timing->ncs_read_pulse > 0)
		config->ncs_read_pulse = ns2cyc(timing->ncs_read_pulse);

	if (timing->nrd_pulse > 0)
		config->nrd_pulse = ns2cyc(timing->nrd_pulse);

	if (timing->ncs_write_pulse > 0)
		config->ncs_write_pulse = ns2cyc(timing->ncs_write_pulse);

	if (timing->nwe_pulse > 0)
		config->nwe_pulse = ns2cyc(timing->nwe_pulse);

	if (timing->read_cycle > 0)
		config->read_cycle = ns2cyc(timing->read_cycle);

	if (timing->write_cycle > 0)
		config->write_cycle = ns2cyc(timing->write_cycle);

	/* Extend read cycle in needed */
	if (timing->ncs_read_recover > 0)
		recover = ns2cyc(timing->ncs_read_recover);
	else
		recover = 1;

	cycle = config->ncs_read_setup + config->ncs_read_pulse + recover;

	if (config->read_cycle < cycle)
		config->read_cycle = cycle;

	/* Extend read cycle in needed */
	if (timing->nrd_recover > 0)
		recover = ns2cyc(timing->nrd_recover);
	else
		recover = 1;

	cycle = config->nrd_setup + config->nrd_pulse + recover;

	if (config->read_cycle < cycle)
		config->read_cycle = cycle;

	/* Extend write cycle in needed */
	if (timing->ncs_write_recover > 0)
		recover = ns2cyc(timing->ncs_write_recover);
	else
		recover = 1;

	cycle = config->ncs_write_setup + config->ncs_write_pulse + recover;

	if (config->write_cycle < cycle)
		config->write_cycle = cycle;

	/* Extend write cycle in needed */
	if (timing->nwe_recover > 0)
		recover = ns2cyc(timing->nwe_recover);
	else
		recover = 1;

	cycle = config->nwe_setup + config->nwe_pulse + recover;

	if (config->write_cycle < cycle)
		config->write_cycle = cycle;
}
EXPORT_SYMBOL(smc_set_timing);

int smc_set_configuration(int cs, const struct smc_config *config)
{
	unsigned long offset;
	u32 setup, pulse, cycle, mode;

	if (!hsmc)
		return -ENODEV;
	if (cs >= NR_CHIP_SELECTS)
		return -EINVAL;

	setup = (HSMC_BF(NWE_SETUP, config->nwe_setup)
		 | HSMC_BF(NCS_WR_SETUP, config->ncs_write_setup)
		 | HSMC_BF(NRD_SETUP, config->nrd_setup)
		 | HSMC_BF(NCS_RD_SETUP, config->ncs_read_setup));
	pulse = (HSMC_BF(NWE_PULSE, config->nwe_pulse)
		 | HSMC_BF(NCS_WR_PULSE, config->ncs_write_pulse)
		 | HSMC_BF(NRD_PULSE, config->nrd_pulse)
		 | HSMC_BF(NCS_RD_PULSE, config->ncs_read_pulse));
	cycle = (HSMC_BF(NWE_CYCLE, config->write_cycle)
		 | HSMC_BF(NRD_CYCLE, config->read_cycle));


	switch (config->bus_width) {
	switch (config->bus_width) {
	case 1:
	case 1:
+41 −10
Original line number Original line Diff line number Diff line
@@ -15,22 +15,50 @@
/*
/*
 * All timing parameters are in nanoseconds.
 * All timing parameters are in nanoseconds.
 */
 */
struct smc_timing {
	/* Delay from address valid to assertion of given strobe */
	int ncs_read_setup;
	int nrd_setup;
	int ncs_write_setup;
	int nwe_setup;

	/* Pulse length of given strobe */
	int ncs_read_pulse;
	int nrd_pulse;
	int ncs_write_pulse;
	int nwe_pulse;

	/* Total cycle length of given operation */
	int read_cycle;
	int write_cycle;

	/* Minimal recovery times, will extend cycle if needed */
	int ncs_read_recover;
	int nrd_recover;
	int ncs_write_recover;
	int nwe_recover;
};

/*
 * All timing parameters are in clock cycles.
 */
struct smc_config {
struct smc_config {

	/* Delay from address valid to assertion of given strobe */
	/* Delay from address valid to assertion of given strobe */
	u16		ncs_read_setup;
	u8		ncs_read_setup;
	u16		nrd_setup;
	u8		nrd_setup;
	u16		ncs_write_setup;
	u8		ncs_write_setup;
	u16		nwe_setup;
	u8		nwe_setup;


	/* Pulse length of given strobe */
	/* Pulse length of given strobe */
	u16		ncs_read_pulse;
	u8		ncs_read_pulse;
	u16		nrd_pulse;
	u8		nrd_pulse;
	u16		ncs_write_pulse;
	u8		ncs_write_pulse;
	u16		nwe_pulse;
	u8		nwe_pulse;


	/* Total cycle length of given operation */
	/* Total cycle length of given operation */
	u16		read_cycle;
	u8		read_cycle;
	u16		write_cycle;
	u8		write_cycle;


	/* Bus width in bytes */
	/* Bus width in bytes */
	u8		bus_width;
	u8		bus_width;
@@ -76,6 +104,9 @@ struct smc_config {
	unsigned int	tdf_mode:1;
	unsigned int	tdf_mode:1;
};
};


extern void smc_set_timing(struct smc_config *config,
			   const struct smc_timing *timing);

extern int smc_set_configuration(int cs, const struct smc_config *config);
extern int smc_set_configuration(int cs, const struct smc_config *config);
extern struct smc_config *smc_get_configuration(int cs);
extern struct smc_config *smc_get_configuration(int cs);