1/* 2 * Static Memory Controller for AT32 chips 3 * 4 * Copyright (C) 2006 Atmel Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10#include <linux/clk.h> 11#include <linux/err.h> 12#include <linux/init.h> 13#include <linux/module.h> 14#include <linux/platform_device.h> 15#include <linux/slab.h> 16 17#include <asm/io.h> 18#include <mach/smc.h> 19 20#include "hsmc.h" 21 22#define NR_CHIP_SELECTS 6 23 24struct hsmc { 25 void __iomem *regs; 26 struct clk *pclk; 27 struct clk *mck; 28}; 29 30static struct hsmc *hsmc; 31 32void smc_set_timing(struct smc_config *config, 33 const struct smc_timing *timing) 34{ 35 int recover; 36 int cycle; 37 38 unsigned long mul; 39 40 /* Reset all SMC timings */ 41 config->ncs_read_setup = 0; 42 config->nrd_setup = 0; 43 config->ncs_write_setup = 0; 44 config->nwe_setup = 0; 45 config->ncs_read_pulse = 0; 46 config->nrd_pulse = 0; 47 config->ncs_write_pulse = 0; 48 config->nwe_pulse = 0; 49 config->read_cycle = 0; 50 config->write_cycle = 0; 51 52 /* 53 * cycles = x / T = x * f 54 * = ((x * 1000000000) * ((f * 65536) / 1000000000)) / 65536 55 * = ((x * 1000000000) * (((f / 10000) * 65536) / 100000)) / 65536 56 */ 57 mul = (clk_get_rate(hsmc->mck) / 10000) << 16; 58 mul /= 100000; 59 60#define ns2cyc(x) ((((x) * mul) + 65535) >> 16) 61 62 if (timing->ncs_read_setup > 0) 63 config->ncs_read_setup = ns2cyc(timing->ncs_read_setup); 64 65 if (timing->nrd_setup > 0) 66 config->nrd_setup = ns2cyc(timing->nrd_setup); 67 68 if (timing->ncs_write_setup > 0) 69 config->ncs_write_setup = ns2cyc(timing->ncs_write_setup); 70 71 if (timing->nwe_setup > 0) 72 config->nwe_setup = ns2cyc(timing->nwe_setup); 73 74 if (timing->ncs_read_pulse > 0) 75 config->ncs_read_pulse = ns2cyc(timing->ncs_read_pulse); 76 77 if (timing->nrd_pulse > 0) 78 config->nrd_pulse = ns2cyc(timing->nrd_pulse); 79 80 if (timing->ncs_write_pulse > 0) 81 config->ncs_write_pulse = ns2cyc(timing->ncs_write_pulse); 82 83 if (timing->nwe_pulse > 0) 84 config->nwe_pulse = ns2cyc(timing->nwe_pulse); 85 86 if (timing->read_cycle > 0) 87 config->read_cycle = ns2cyc(timing->read_cycle); 88 89 if (timing->write_cycle > 0) 90 config->write_cycle = ns2cyc(timing->write_cycle); 91 92 /* Extend read cycle in needed */ 93 if (timing->ncs_read_recover > 0) 94 recover = ns2cyc(timing->ncs_read_recover); 95 else 96 recover = 1; 97 98 cycle = config->ncs_read_setup + config->ncs_read_pulse + recover; 99 100 if (config->read_cycle < cycle) 101 config->read_cycle = cycle; 102 103 /* Extend read cycle in needed */ 104 if (timing->nrd_recover > 0) 105 recover = ns2cyc(timing->nrd_recover); 106 else 107 recover = 1; 108 109 cycle = config->nrd_setup + config->nrd_pulse + recover; 110 111 if (config->read_cycle < cycle) 112 config->read_cycle = cycle; 113 114 /* Extend write cycle in needed */ 115 if (timing->ncs_write_recover > 0) 116 recover = ns2cyc(timing->ncs_write_recover); 117 else 118 recover = 1; 119 120 cycle = config->ncs_write_setup + config->ncs_write_pulse + recover; 121 122 if (config->write_cycle < cycle) 123 config->write_cycle = cycle; 124 125 /* Extend write cycle in needed */ 126 if (timing->nwe_recover > 0) 127 recover = ns2cyc(timing->nwe_recover); 128 else 129 recover = 1; 130 131 cycle = config->nwe_setup + config->nwe_pulse + recover; 132 133 if (config->write_cycle < cycle) 134 config->write_cycle = cycle; 135} 136EXPORT_SYMBOL(smc_set_timing); 137 138int smc_set_configuration(int cs, const struct smc_config *config) 139{ 140 unsigned long offset; 141 u32 setup, pulse, cycle, mode; 142 143 if (!hsmc) 144 return -ENODEV; 145 if (cs >= NR_CHIP_SELECTS) 146 return -EINVAL; 147 148 setup = (HSMC_BF(NWE_SETUP, config->nwe_setup) 149 | HSMC_BF(NCS_WR_SETUP, config->ncs_write_setup) 150 | HSMC_BF(NRD_SETUP, config->nrd_setup) 151 | HSMC_BF(NCS_RD_SETUP, config->ncs_read_setup)); 152 pulse = (HSMC_BF(NWE_PULSE, config->nwe_pulse) 153 | HSMC_BF(NCS_WR_PULSE, config->ncs_write_pulse) 154 | HSMC_BF(NRD_PULSE, config->nrd_pulse) 155 | HSMC_BF(NCS_RD_PULSE, config->ncs_read_pulse)); 156 cycle = (HSMC_BF(NWE_CYCLE, config->write_cycle) 157 | HSMC_BF(NRD_CYCLE, config->read_cycle)); 158 159 switch (config->bus_width) { 160 case 1: 161 mode = HSMC_BF(DBW, HSMC_DBW_8_BITS); 162 break; 163 case 2: 164 mode = HSMC_BF(DBW, HSMC_DBW_16_BITS); 165 break; 166 case 4: 167 mode = HSMC_BF(DBW, HSMC_DBW_32_BITS); 168 break; 169 default: 170 return -EINVAL; 171 } 172 173 switch (config->nwait_mode) { 174 case 0: 175 mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_DISABLED); 176 break; 177 case 1: 178 mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_RESERVED); 179 break; 180 case 2: 181 mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_FROZEN); 182 break; 183 case 3: 184 mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_READY); 185 break; 186 default: 187 return -EINVAL; 188 } 189 190 if (config->tdf_cycles) { 191 mode |= HSMC_BF(TDF_CYCLES, config->tdf_cycles); 192 } 193 194 if (config->nrd_controlled) 195 mode |= HSMC_BIT(READ_MODE); 196 if (config->nwe_controlled) 197 mode |= HSMC_BIT(WRITE_MODE); 198 if (config->byte_write) 199 mode |= HSMC_BIT(BAT); 200 if (config->tdf_mode) 201 mode |= HSMC_BIT(TDF_MODE); 202 203 pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n", 204 cs, setup, pulse, cycle, mode); 205 206 offset = cs * 0x10; 207 hsmc_writel(hsmc, SETUP0 + offset, setup); 208 hsmc_writel(hsmc, PULSE0 + offset, pulse); 209 hsmc_writel(hsmc, CYCLE0 + offset, cycle); 210 hsmc_writel(hsmc, MODE0 + offset, mode); 211 hsmc_readl(hsmc, MODE0); /* I/O barrier */ 212 213 return 0; 214} 215EXPORT_SYMBOL(smc_set_configuration); 216 217static int hsmc_probe(struct platform_device *pdev) 218{ 219 struct resource *regs; 220 struct clk *pclk, *mck; 221 int ret; 222 223 if (hsmc) 224 return -EBUSY; 225 226 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 227 if (!regs) 228 return -ENXIO; 229 pclk = clk_get(&pdev->dev, "pclk"); 230 if (IS_ERR(pclk)) 231 return PTR_ERR(pclk); 232 mck = clk_get(&pdev->dev, "mck"); 233 if (IS_ERR(mck)) { 234 ret = PTR_ERR(mck); 235 goto out_put_pclk; 236 } 237 238 ret = -ENOMEM; 239 hsmc = kzalloc(sizeof(struct hsmc), GFP_KERNEL); 240 if (!hsmc) 241 goto out_put_clocks; 242 243 clk_enable(pclk); 244 clk_enable(mck); 245 246 hsmc->pclk = pclk; 247 hsmc->mck = mck; 248 hsmc->regs = ioremap(regs->start, resource_size(regs)); 249 if (!hsmc->regs) 250 goto out_disable_clocks; 251 252 dev_info(&pdev->dev, "Atmel Static Memory Controller at 0x%08lx\n", 253 (unsigned long)regs->start); 254 255 platform_set_drvdata(pdev, hsmc); 256 257 return 0; 258 259out_disable_clocks: 260 clk_disable(mck); 261 clk_disable(pclk); 262 kfree(hsmc); 263out_put_clocks: 264 clk_put(mck); 265out_put_pclk: 266 clk_put(pclk); 267 hsmc = NULL; 268 return ret; 269} 270 271static struct platform_driver hsmc_driver = { 272 .probe = hsmc_probe, 273 .driver = { 274 .name = "smc", 275 }, 276}; 277 278static int __init hsmc_init(void) 279{ 280 return platform_driver_register(&hsmc_driver); 281} 282core_initcall(hsmc_init); 283