Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.6-rc2 415 lines 11 kB view raw
1/* 2 * SuperH Mobile SDHI 3 * 4 * Copyright (C) 2016 Sang Engineering, Wolfram Sang 5 * Copyright (C) 2015-16 Renesas Electronics Corporation 6 * Copyright (C) 2009 Magnus Damm 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 version 2 as 10 * published by the Free Software Foundation. 11 * 12 * Based on "Compaq ASIC3 support": 13 * 14 * Copyright 2001 Compaq Computer Corporation. 15 * Copyright 2004-2005 Phil Blundell 16 * Copyright 2007-2008 OpenedHand Ltd. 17 * 18 * Authors: Phil Blundell <pb@handhelds.org>, 19 * Samuel Ortiz <sameo@openedhand.com> 20 * 21 */ 22 23#include <linux/kernel.h> 24#include <linux/clk.h> 25#include <linux/slab.h> 26#include <linux/mod_devicetable.h> 27#include <linux/module.h> 28#include <linux/of_device.h> 29#include <linux/platform_device.h> 30#include <linux/mmc/host.h> 31#include <linux/mmc/sh_mobile_sdhi.h> 32#include <linux/mfd/tmio.h> 33#include <linux/sh_dma.h> 34#include <linux/delay.h> 35 36#include "tmio_mmc.h" 37 38#define EXT_ACC 0xe4 39 40#define host_to_priv(host) container_of((host)->pdata, struct sh_mobile_sdhi, mmc_data) 41 42struct sh_mobile_sdhi_of_data { 43 unsigned long tmio_flags; 44 unsigned long capabilities; 45 unsigned long capabilities2; 46 enum dma_slave_buswidth dma_buswidth; 47 dma_addr_t dma_rx_offset; 48 unsigned bus_shift; 49}; 50 51static const struct sh_mobile_sdhi_of_data sh_mobile_sdhi_of_cfg[] = { 52 { 53 .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, 54 }, 55}; 56 57static const struct sh_mobile_sdhi_of_data of_rcar_gen1_compatible = { 58 .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | 59 TMIO_MMC_CLK_ACTUAL, 60 .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, 61}; 62 63static const struct sh_mobile_sdhi_of_data of_rcar_gen2_compatible = { 64 .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | 65 TMIO_MMC_CLK_ACTUAL | TMIO_MMC_FAST_CLK_CHG, 66 .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, 67 .dma_buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES, 68 .dma_rx_offset = 0x2000, 69}; 70 71static const struct sh_mobile_sdhi_of_data of_rcar_gen3_compatible = { 72 .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | 73 TMIO_MMC_CLK_ACTUAL | TMIO_MMC_FAST_CLK_CHG, 74 .capabilities = MMC_CAP_SD_HIGHSPEED, 75 .bus_shift = 2, 76}; 77 78static const struct of_device_id sh_mobile_sdhi_of_match[] = { 79 { .compatible = "renesas,sdhi-shmobile" }, 80 { .compatible = "renesas,sdhi-sh7372" }, 81 { .compatible = "renesas,sdhi-sh73a0", .data = &sh_mobile_sdhi_of_cfg[0], }, 82 { .compatible = "renesas,sdhi-r8a73a4", .data = &sh_mobile_sdhi_of_cfg[0], }, 83 { .compatible = "renesas,sdhi-r8a7740", .data = &sh_mobile_sdhi_of_cfg[0], }, 84 { .compatible = "renesas,sdhi-r8a7778", .data = &of_rcar_gen1_compatible, }, 85 { .compatible = "renesas,sdhi-r8a7779", .data = &of_rcar_gen1_compatible, }, 86 { .compatible = "renesas,sdhi-r8a7790", .data = &of_rcar_gen2_compatible, }, 87 { .compatible = "renesas,sdhi-r8a7791", .data = &of_rcar_gen2_compatible, }, 88 { .compatible = "renesas,sdhi-r8a7792", .data = &of_rcar_gen2_compatible, }, 89 { .compatible = "renesas,sdhi-r8a7793", .data = &of_rcar_gen2_compatible, }, 90 { .compatible = "renesas,sdhi-r8a7794", .data = &of_rcar_gen2_compatible, }, 91 { .compatible = "renesas,sdhi-r8a7795", .data = &of_rcar_gen3_compatible, }, 92 {}, 93}; 94MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); 95 96struct sh_mobile_sdhi { 97 struct clk *clk; 98 struct tmio_mmc_data mmc_data; 99 struct tmio_mmc_dma dma_priv; 100}; 101 102static void sh_mobile_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width) 103{ 104 u32 val; 105 106 /* 107 * see also 108 * sh_mobile_sdhi_of_data :: dma_buswidth 109 */ 110 switch (sd_ctrl_read16(host, CTL_VERSION)) { 111 case 0x490C: 112 val = (width == 32) ? 0x0001 : 0x0000; 113 break; 114 case 0xCB0D: 115 val = (width == 32) ? 0x0000 : 0x0001; 116 break; 117 case 0xCC10: /* Gen3, SD only */ 118 case 0xCD10: /* Gen3, SD + MMC */ 119 if (width == 64) 120 val = 0x0000; 121 else if (width == 32) 122 val = 0x0101; 123 else 124 val = 0x0001; 125 break; 126 default: 127 /* nothing to do */ 128 return; 129 } 130 131 sd_ctrl_write16(host, EXT_ACC, val); 132} 133 134static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f) 135{ 136 struct mmc_host *mmc = platform_get_drvdata(pdev); 137 struct tmio_mmc_host *host = mmc_priv(mmc); 138 struct sh_mobile_sdhi *priv = host_to_priv(host); 139 int ret = clk_prepare_enable(priv->clk); 140 if (ret < 0) 141 return ret; 142 143 *f = clk_get_rate(priv->clk); 144 145 /* enable 16bit data access on SDBUF as default */ 146 sh_mobile_sdhi_sdbuf_width(host, 16); 147 148 return 0; 149} 150 151static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) 152{ 153 struct mmc_host *mmc = platform_get_drvdata(pdev); 154 struct tmio_mmc_host *host = mmc_priv(mmc); 155 struct sh_mobile_sdhi *priv = host_to_priv(host); 156 clk_disable_unprepare(priv->clk); 157} 158 159static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) 160{ 161 int timeout = 1000; 162 163 while (--timeout && !(sd_ctrl_read16(host, CTL_STATUS2) & (1 << 13))) 164 udelay(1); 165 166 if (!timeout) { 167 dev_warn(&host->pdev->dev, "timeout waiting for SD bus idle\n"); 168 return -EBUSY; 169 } 170 171 return 0; 172} 173 174static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) 175{ 176 switch (addr) 177 { 178 case CTL_SD_CMD: 179 case CTL_STOP_INTERNAL_ACTION: 180 case CTL_XFER_BLK_COUNT: 181 case CTL_SD_CARD_CLK_CTL: 182 case CTL_SD_XFER_LEN: 183 case CTL_SD_MEM_CARD_OPT: 184 case CTL_TRANSACTION_CTL: 185 case CTL_DMA_ENABLE: 186 case EXT_ACC: 187 return sh_mobile_sdhi_wait_idle(host); 188 } 189 190 return 0; 191} 192 193static int sh_mobile_sdhi_multi_io_quirk(struct mmc_card *card, 194 unsigned int direction, int blk_size) 195{ 196 /* 197 * In Renesas controllers, when performing a 198 * multiple block read of one or two blocks, 199 * depending on the timing with which the 200 * response register is read, the response 201 * value may not be read properly. 202 * Use single block read for this HW bug 203 */ 204 if ((direction == MMC_DATA_READ) && 205 blk_size == 2) 206 return 1; 207 208 return blk_size; 209} 210 211static void sh_mobile_sdhi_enable_dma(struct tmio_mmc_host *host, bool enable) 212{ 213 sd_ctrl_write16(host, CTL_DMA_ENABLE, enable ? 2 : 0); 214 215 /* enable 32bit access if DMA mode if possibile */ 216 sh_mobile_sdhi_sdbuf_width(host, enable ? 32 : 16); 217} 218 219static int sh_mobile_sdhi_probe(struct platform_device *pdev) 220{ 221 const struct of_device_id *of_id = 222 of_match_device(sh_mobile_sdhi_of_match, &pdev->dev); 223 struct sh_mobile_sdhi *priv; 224 struct tmio_mmc_data *mmc_data; 225 struct tmio_mmc_data *mmd = pdev->dev.platform_data; 226 struct tmio_mmc_host *host; 227 struct resource *res; 228 int irq, ret, i = 0; 229 bool multiplexed_isr = true; 230 struct tmio_mmc_dma *dma_priv; 231 232 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 233 if (!res) 234 return -EINVAL; 235 236 priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_mobile_sdhi), GFP_KERNEL); 237 if (!priv) 238 return -ENOMEM; 239 240 mmc_data = &priv->mmc_data; 241 dma_priv = &priv->dma_priv; 242 243 priv->clk = devm_clk_get(&pdev->dev, NULL); 244 if (IS_ERR(priv->clk)) { 245 ret = PTR_ERR(priv->clk); 246 dev_err(&pdev->dev, "cannot get clock: %d\n", ret); 247 goto eprobe; 248 } 249 250 host = tmio_mmc_host_alloc(pdev); 251 if (!host) { 252 ret = -ENOMEM; 253 goto eprobe; 254 } 255 256 if (of_id && of_id->data) { 257 const struct sh_mobile_sdhi_of_data *of_data = of_id->data; 258 259 mmc_data->flags |= of_data->tmio_flags; 260 mmc_data->capabilities |= of_data->capabilities; 261 mmc_data->capabilities2 |= of_data->capabilities2; 262 mmc_data->dma_rx_offset = of_data->dma_rx_offset; 263 dma_priv->dma_buswidth = of_data->dma_buswidth; 264 host->bus_shift = of_data->bus_shift; 265 } 266 267 host->dma = dma_priv; 268 host->write16_hook = sh_mobile_sdhi_write16_hook; 269 host->clk_enable = sh_mobile_sdhi_clk_enable; 270 host->clk_disable = sh_mobile_sdhi_clk_disable; 271 host->multi_io_quirk = sh_mobile_sdhi_multi_io_quirk; 272 273 /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ 274 if (!host->bus_shift && resource_size(res) > 0x100) /* old way to determine the shift */ 275 host->bus_shift = 1; 276 277 if (mmd) 278 *mmc_data = *mmd; 279 280 dma_priv->filter = shdma_chan_filter; 281 dma_priv->enable = sh_mobile_sdhi_enable_dma; 282 283 mmc_data->alignment_shift = 1; /* 2-byte alignment */ 284 mmc_data->capabilities |= MMC_CAP_MMC_HIGHSPEED; 285 286 /* 287 * All SDHI blocks support 2-byte and larger block sizes in 4-bit 288 * bus width mode. 289 */ 290 mmc_data->flags |= TMIO_MMC_BLKSZ_2BYTES; 291 292 /* 293 * All SDHI blocks support SDIO IRQ signalling. 294 */ 295 mmc_data->flags |= TMIO_MMC_SDIO_IRQ; 296 297 /* 298 * All SDHI have CMD12 controll bit 299 */ 300 mmc_data->flags |= TMIO_MMC_HAVE_CMD12_CTRL; 301 302 /* 303 * All SDHI need SDIO_INFO1 reserved bit 304 */ 305 mmc_data->flags |= TMIO_MMC_SDIO_STATUS_QUIRK; 306 307 ret = tmio_mmc_host_probe(host, mmc_data); 308 if (ret < 0) 309 goto efree; 310 311 /* 312 * Allow one or more specific (named) ISRs or 313 * one or more multiplexed (un-named) ISRs. 314 */ 315 316 irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT); 317 if (irq >= 0) { 318 multiplexed_isr = false; 319 ret = devm_request_irq(&pdev->dev, irq, tmio_mmc_card_detect_irq, 0, 320 dev_name(&pdev->dev), host); 321 if (ret) 322 goto eirq; 323 } 324 325 irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO); 326 if (irq >= 0) { 327 multiplexed_isr = false; 328 ret = devm_request_irq(&pdev->dev, irq, tmio_mmc_sdio_irq, 0, 329 dev_name(&pdev->dev), host); 330 if (ret) 331 goto eirq; 332 } 333 334 irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDCARD); 335 if (irq >= 0) { 336 multiplexed_isr = false; 337 ret = devm_request_irq(&pdev->dev, irq, tmio_mmc_sdcard_irq, 0, 338 dev_name(&pdev->dev), host); 339 if (ret) 340 goto eirq; 341 } else if (!multiplexed_isr) { 342 dev_err(&pdev->dev, 343 "Principal SD-card IRQ is missing among named interrupts\n"); 344 ret = irq; 345 goto eirq; 346 } 347 348 if (multiplexed_isr) { 349 while (1) { 350 irq = platform_get_irq(pdev, i); 351 if (irq < 0) 352 break; 353 i++; 354 ret = devm_request_irq(&pdev->dev, irq, tmio_mmc_irq, 0, 355 dev_name(&pdev->dev), host); 356 if (ret) 357 goto eirq; 358 } 359 360 /* There must be at least one IRQ source */ 361 if (!i) { 362 ret = irq; 363 goto eirq; 364 } 365 } 366 367 dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n", 368 mmc_hostname(host->mmc), (unsigned long) 369 (platform_get_resource(pdev, IORESOURCE_MEM, 0)->start), 370 host->mmc->f_max / 1000000); 371 372 return ret; 373 374eirq: 375 tmio_mmc_host_remove(host); 376efree: 377 tmio_mmc_host_free(host); 378eprobe: 379 return ret; 380} 381 382static int sh_mobile_sdhi_remove(struct platform_device *pdev) 383{ 384 struct mmc_host *mmc = platform_get_drvdata(pdev); 385 struct tmio_mmc_host *host = mmc_priv(mmc); 386 387 tmio_mmc_host_remove(host); 388 389 return 0; 390} 391 392static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { 393 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 394 pm_runtime_force_resume) 395 SET_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend, 396 tmio_mmc_host_runtime_resume, 397 NULL) 398}; 399 400static struct platform_driver sh_mobile_sdhi_driver = { 401 .driver = { 402 .name = "sh_mobile_sdhi", 403 .pm = &tmio_mmc_dev_pm_ops, 404 .of_match_table = sh_mobile_sdhi_of_match, 405 }, 406 .probe = sh_mobile_sdhi_probe, 407 .remove = sh_mobile_sdhi_remove, 408}; 409 410module_platform_driver(sh_mobile_sdhi_driver); 411 412MODULE_DESCRIPTION("SuperH Mobile SDHI driver"); 413MODULE_AUTHOR("Magnus Damm"); 414MODULE_LICENSE("GPL v2"); 415MODULE_ALIAS("platform:sh_mobile_sdhi");