Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v4.4-rc8 218 lines 5.9 kB view raw
1/* 2 * include/linux/mmc/sh_mmcif.h 3 * 4 * platform data for eMMC driver 5 * 6 * Copyright (C) 2010 Renesas Solutions Corp. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License. 11 * 12 */ 13 14#ifndef LINUX_MMC_SH_MMCIF_H 15#define LINUX_MMC_SH_MMCIF_H 16 17#include <linux/io.h> 18#include <linux/platform_device.h> 19 20/* 21 * MMCIF : CE_CLK_CTRL [19:16] 22 * 1000 : Peripheral clock / 512 23 * 0111 : Peripheral clock / 256 24 * 0110 : Peripheral clock / 128 25 * 0101 : Peripheral clock / 64 26 * 0100 : Peripheral clock / 32 27 * 0011 : Peripheral clock / 16 28 * 0010 : Peripheral clock / 8 29 * 0001 : Peripheral clock / 4 30 * 0000 : Peripheral clock / 2 31 * 1111 : Peripheral clock (sup_pclk set '1') 32 */ 33 34struct sh_mmcif_plat_data { 35 int (*get_cd)(struct platform_device *pdef); 36 unsigned int slave_id_tx; /* embedded slave_id_[tr]x */ 37 unsigned int slave_id_rx; 38 bool use_cd_gpio : 1; 39 bool ccs_unsupported : 1; 40 bool clk_ctrl2_present : 1; 41 unsigned int cd_gpio; 42 u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */ 43 unsigned long caps; 44 u32 ocr; 45}; 46 47#define MMCIF_CE_CMD_SET 0x00000000 48#define MMCIF_CE_ARG 0x00000008 49#define MMCIF_CE_ARG_CMD12 0x0000000C 50#define MMCIF_CE_CMD_CTRL 0x00000010 51#define MMCIF_CE_BLOCK_SET 0x00000014 52#define MMCIF_CE_CLK_CTRL 0x00000018 53#define MMCIF_CE_BUF_ACC 0x0000001C 54#define MMCIF_CE_RESP3 0x00000020 55#define MMCIF_CE_RESP2 0x00000024 56#define MMCIF_CE_RESP1 0x00000028 57#define MMCIF_CE_RESP0 0x0000002C 58#define MMCIF_CE_RESP_CMD12 0x00000030 59#define MMCIF_CE_DATA 0x00000034 60#define MMCIF_CE_INT 0x00000040 61#define MMCIF_CE_INT_MASK 0x00000044 62#define MMCIF_CE_HOST_STS1 0x00000048 63#define MMCIF_CE_HOST_STS2 0x0000004C 64#define MMCIF_CE_CLK_CTRL2 0x00000070 65#define MMCIF_CE_VERSION 0x0000007C 66 67/* CE_BUF_ACC */ 68#define BUF_ACC_DMAWEN (1 << 25) 69#define BUF_ACC_DMAREN (1 << 24) 70#define BUF_ACC_BUSW_32 (0 << 17) 71#define BUF_ACC_BUSW_16 (1 << 17) 72#define BUF_ACC_ATYP (1 << 16) 73 74/* CE_CLK_CTRL */ 75#define CLK_ENABLE (1 << 24) /* 1: output mmc clock */ 76#define CLK_CLEAR (0xf << 16) 77#define CLK_SUP_PCLK (0xf << 16) 78#define CLKDIV_4 (1 << 16) /* mmc clock frequency. 79 * n: bus clock/(2^(n+1)) */ 80#define CLKDIV_256 (7 << 16) /* mmc clock frequency. (see above) */ 81#define SRSPTO_256 (2 << 12) /* resp timeout */ 82#define SRBSYTO_29 (0xf << 8) /* resp busy timeout */ 83#define SRWDTO_29 (0xf << 4) /* read/write timeout */ 84#define SCCSTO_29 (0xf << 0) /* ccs timeout */ 85 86/* CE_VERSION */ 87#define SOFT_RST_ON (1 << 31) 88#define SOFT_RST_OFF 0 89 90static inline u32 sh_mmcif_readl(void __iomem *addr, int reg) 91{ 92 return __raw_readl(addr + reg); 93} 94 95static inline void sh_mmcif_writel(void __iomem *addr, int reg, u32 val) 96{ 97 __raw_writel(val, addr + reg); 98} 99 100#define SH_MMCIF_BBS 512 /* boot block size */ 101 102static inline void sh_mmcif_boot_cmd_send(void __iomem *base, 103 unsigned long cmd, unsigned long arg) 104{ 105 sh_mmcif_writel(base, MMCIF_CE_INT, 0); 106 sh_mmcif_writel(base, MMCIF_CE_ARG, arg); 107 sh_mmcif_writel(base, MMCIF_CE_CMD_SET, cmd); 108} 109 110static inline int sh_mmcif_boot_cmd_poll(void __iomem *base, unsigned long mask) 111{ 112 unsigned long tmp; 113 int cnt; 114 115 for (cnt = 0; cnt < 1000000; cnt++) { 116 tmp = sh_mmcif_readl(base, MMCIF_CE_INT); 117 if (tmp & mask) { 118 sh_mmcif_writel(base, MMCIF_CE_INT, tmp & ~mask); 119 return 0; 120 } 121 } 122 123 return -1; 124} 125 126static inline int sh_mmcif_boot_cmd(void __iomem *base, 127 unsigned long cmd, unsigned long arg) 128{ 129 sh_mmcif_boot_cmd_send(base, cmd, arg); 130 return sh_mmcif_boot_cmd_poll(base, 0x00010000); 131} 132 133static inline int sh_mmcif_boot_do_read_single(void __iomem *base, 134 unsigned int block_nr, 135 unsigned long *buf) 136{ 137 int k; 138 139 /* CMD13 - Status */ 140 sh_mmcif_boot_cmd(base, 0x0d400000, 0x00010000); 141 142 if (sh_mmcif_readl(base, MMCIF_CE_RESP0) != 0x0900) 143 return -1; 144 145 /* CMD17 - Read */ 146 sh_mmcif_boot_cmd(base, 0x11480000, block_nr * SH_MMCIF_BBS); 147 if (sh_mmcif_boot_cmd_poll(base, 0x00100000) < 0) 148 return -1; 149 150 for (k = 0; k < (SH_MMCIF_BBS / 4); k++) 151 buf[k] = sh_mmcif_readl(base, MMCIF_CE_DATA); 152 153 return 0; 154} 155 156static inline int sh_mmcif_boot_do_read(void __iomem *base, 157 unsigned long first_block, 158 unsigned long nr_blocks, 159 void *buf) 160{ 161 unsigned long k; 162 int ret = 0; 163 164 /* In data transfer mode: Set clock to Bus clock/4 (about 20Mhz) */ 165 sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 166 CLK_ENABLE | CLKDIV_4 | SRSPTO_256 | 167 SRBSYTO_29 | SRWDTO_29 | SCCSTO_29); 168 169 /* CMD9 - Get CSD */ 170 sh_mmcif_boot_cmd(base, 0x09806000, 0x00010000); 171 172 /* CMD7 - Select the card */ 173 sh_mmcif_boot_cmd(base, 0x07400000, 0x00010000); 174 175 /* CMD16 - Set the block size */ 176 sh_mmcif_boot_cmd(base, 0x10400000, SH_MMCIF_BBS); 177 178 for (k = 0; !ret && k < nr_blocks; k++) 179 ret = sh_mmcif_boot_do_read_single(base, first_block + k, 180 buf + (k * SH_MMCIF_BBS)); 181 182 return ret; 183} 184 185static inline void sh_mmcif_boot_init(void __iomem *base) 186{ 187 /* reset */ 188 sh_mmcif_writel(base, MMCIF_CE_VERSION, SOFT_RST_ON); 189 sh_mmcif_writel(base, MMCIF_CE_VERSION, SOFT_RST_OFF); 190 191 /* byte swap */ 192 sh_mmcif_writel(base, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP); 193 194 /* Set block size in MMCIF hardware */ 195 sh_mmcif_writel(base, MMCIF_CE_BLOCK_SET, SH_MMCIF_BBS); 196 197 /* Enable the clock, set it to Bus clock/256 (about 325Khz). */ 198 sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 199 CLK_ENABLE | CLKDIV_256 | SRSPTO_256 | 200 SRBSYTO_29 | SRWDTO_29 | SCCSTO_29); 201 202 /* CMD0 */ 203 sh_mmcif_boot_cmd(base, 0x00000040, 0); 204 205 /* CMD1 - Get OCR */ 206 do { 207 sh_mmcif_boot_cmd(base, 0x01405040, 0x40300000); /* CMD1 */ 208 } while ((sh_mmcif_readl(base, MMCIF_CE_RESP0) & 0x80000000) 209 != 0x80000000); 210 211 /* CMD2 - Get CID */ 212 sh_mmcif_boot_cmd(base, 0x02806040, 0); 213 214 /* CMD3 - Set card relative address */ 215 sh_mmcif_boot_cmd(base, 0x03400040, 0x00010000); 216} 217 218#endif /* LINUX_MMC_SH_MMCIF_H */