1/* 2 * linux/arch/arm/mach-at91/sam9_smc.c 3 * 4 * Copyright (C) 2008 Andrew Victor 5 * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12#include <linux/module.h> 13#include <linux/io.h> 14#include <linux/of.h> 15#include <linux/of_address.h> 16 17#include <mach/at91sam9_smc.h> 18 19#include "sam9_smc.h" 20 21 22#define AT91_SMC_CS(id, n) (smc_base_addr[id] + ((n) * 0x10)) 23 24static void __iomem *smc_base_addr[2]; 25 26static void sam9_smc_cs_write_mode(void __iomem *base, 27 struct sam9_smc_config *config) 28{ 29 __raw_writel(config->mode 30 | AT91_SMC_TDF_(config->tdf_cycles), 31 base + AT91_SMC_MODE); 32} 33 34void sam9_smc_write_mode(int id, int cs, 35 struct sam9_smc_config *config) 36{ 37 sam9_smc_cs_write_mode(AT91_SMC_CS(id, cs), config); 38} 39EXPORT_SYMBOL_GPL(sam9_smc_write_mode); 40 41static void sam9_smc_cs_configure(void __iomem *base, 42 struct sam9_smc_config *config) 43{ 44 45 /* Setup register */ 46 __raw_writel(AT91_SMC_NWESETUP_(config->nwe_setup) 47 | AT91_SMC_NCS_WRSETUP_(config->ncs_write_setup) 48 | AT91_SMC_NRDSETUP_(config->nrd_setup) 49 | AT91_SMC_NCS_RDSETUP_(config->ncs_read_setup), 50 base + AT91_SMC_SETUP); 51 52 /* Pulse register */ 53 __raw_writel(AT91_SMC_NWEPULSE_(config->nwe_pulse) 54 | AT91_SMC_NCS_WRPULSE_(config->ncs_write_pulse) 55 | AT91_SMC_NRDPULSE_(config->nrd_pulse) 56 | AT91_SMC_NCS_RDPULSE_(config->ncs_read_pulse), 57 base + AT91_SMC_PULSE); 58 59 /* Cycle register */ 60 __raw_writel(AT91_SMC_NWECYCLE_(config->write_cycle) 61 | AT91_SMC_NRDCYCLE_(config->read_cycle), 62 base + AT91_SMC_CYCLE); 63 64 /* Mode register */ 65 sam9_smc_cs_write_mode(base, config); 66} 67 68void sam9_smc_configure(int id, int cs, 69 struct sam9_smc_config *config) 70{ 71 sam9_smc_cs_configure(AT91_SMC_CS(id, cs), config); 72} 73EXPORT_SYMBOL_GPL(sam9_smc_configure); 74 75static void sam9_smc_cs_read_mode(void __iomem *base, 76 struct sam9_smc_config *config) 77{ 78 u32 val = __raw_readl(base + AT91_SMC_MODE); 79 80 config->mode = (val & ~AT91_SMC_NWECYCLE); 81 config->tdf_cycles = (val & AT91_SMC_NWECYCLE) >> 16 ; 82} 83 84void sam9_smc_read_mode(int id, int cs, 85 struct sam9_smc_config *config) 86{ 87 sam9_smc_cs_read_mode(AT91_SMC_CS(id, cs), config); 88} 89EXPORT_SYMBOL_GPL(sam9_smc_read_mode); 90 91static void sam9_smc_cs_read(void __iomem *base, 92 struct sam9_smc_config *config) 93{ 94 u32 val; 95 96 /* Setup register */ 97 val = __raw_readl(base + AT91_SMC_SETUP); 98 99 config->nwe_setup = val & AT91_SMC_NWESETUP; 100 config->ncs_write_setup = (val & AT91_SMC_NCS_WRSETUP) >> 8; 101 config->nrd_setup = (val & AT91_SMC_NRDSETUP) >> 16; 102 config->ncs_read_setup = (val & AT91_SMC_NCS_RDSETUP) >> 24; 103 104 /* Pulse register */ 105 val = __raw_readl(base + AT91_SMC_PULSE); 106 107 config->nwe_pulse = val & AT91_SMC_NWEPULSE; 108 config->ncs_write_pulse = (val & AT91_SMC_NCS_WRPULSE) >> 8; 109 config->nrd_pulse = (val & AT91_SMC_NRDPULSE) >> 16; 110 config->ncs_read_pulse = (val & AT91_SMC_NCS_RDPULSE) >> 24; 111 112 /* Cycle register */ 113 val = __raw_readl(base + AT91_SMC_CYCLE); 114 115 config->write_cycle = val & AT91_SMC_NWECYCLE; 116 config->read_cycle = (val & AT91_SMC_NRDCYCLE) >> 16; 117 118 /* Mode register */ 119 sam9_smc_cs_read_mode(base, config); 120} 121 122void sam9_smc_read(int id, int cs, struct sam9_smc_config *config) 123{ 124 sam9_smc_cs_read(AT91_SMC_CS(id, cs), config); 125} 126 127void __init at91sam9_ioremap_smc(int id, u32 addr) 128{ 129 if (id > 1) { 130 pr_warn("%s: id > 2\n", __func__); 131 return; 132 } 133 smc_base_addr[id] = ioremap(addr, 512); 134 if (!smc_base_addr[id]) 135 pr_warn("Impossible to ioremap smc.%d 0x%x\n", id, addr); 136} 137