123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- /*
- *
- * drivers/media/tdmb/tdmb_ebi.c
- *
- * tdmb driver
- *
- * Copyright (C) (2011, Samsung Electronics)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #include <linux/io.h>
- #include <linux/of_gpio.h>
- #include <linux/clk.h>
- #include <linux/slab.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <plat/gpio-cfg.h>
- #include <plat/regs-srom.h>
- #include <mach/gpio.h>
- #include "tdmb.h"
- static struct tdmb_ebi_dt_data *ebi_dt_pdata;
- static void __iomem *v_addr_ebi_cs_base;
- /* SROMC bank attributes in BW (Bus width and Wait control) register */
- enum sromc_bank_attr {
- SROMC_DATA_16 = 0x1, /* 16-bit data bus */
- SROMC_BYTE_ADDR = 0x2, /* Byte base address */
- SROMC_WAIT_EN = 0x4, /* Wait enabled */
- SROMC_BYTE_EN = 0x8, /* Byte access enabled */
- SROMC_ATTR_MASK = 0xF
- };
- /* SROMC bank configuration */
- struct sromc_bank_cfg {
- unsigned csn; /* CSn # */
- unsigned attr; /* SROMC bank attributes */
- unsigned size; /* Size of a memory */
- unsigned addr; /* Start address (physical) */
- };
- /* SROMC bank access timing configuration */
- struct sromc_timing_cfg {
- u32 tacs; /* Address set-up before CSn */
- u32 tcos; /* Chip selection set-up before OEn */
- u32 tacc; /* Access cycle */
- u32 tcoh; /* Chip selection hold on OEn */
- u32 tcah; /* Address holding time after CSn */
- u32 tacp; /* Page mode access cycle at Page mode */
- u32 pmc; /* Page Mode config */
- };
- /**
- * sromc_enable
- *
- * Enables SROM controller (SROMC) block
- *
- */
- static int sromc_enable(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- struct clk *clk;
- clk = devm_clk_get(dev, "sromc_clk");
- if (IS_ERR(clk)) {
- DPRINTK("Failed to get tdmb_sromc clock\n");
- return -1;
- }
- if (clk_prepare_enable(clk)) {
- DPRINTK("%s: clk_prepare_enable failed\n", __func__);
- return -1;
- }
- return 0;
- }
- /**
- * sromc_config_demux_gpio
- *
- * Configures GPIO pins for REn, WEn, LBn, UBn, address bus, and data bus
- * as demux mode
- *
- * Returns 0 if there is no error
- *
- */
- static int sromc_config_demux_gpio(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- struct pinctrl *pinctrl;
- pinctrl = devm_pinctrl_get_select_default(dev);
- if (IS_ERR(pinctrl))
- DPRINTK("%s: Failed to configure pinctrl\n", __func__);
- return 0;
- }
- /**
- * sromc_config_access_attr
- * @csn: CSn number
- * @attr: SROMC attribute for this CSn
- *
- * Configures SROMC attribute for a CSn
- *
- */
- static void sromc_config_access_attr(unsigned int csn, unsigned int attr)
- {
- unsigned int bw = 0; /* Bus width and Wait control */
- DPRINTK("%s: for CSn%d\n", __func__, csn);
- bw = __raw_readl(S5P_SROM_BW);
- DPRINTK("%s: old BW setting = 0x%08X\n", __func__, bw);
- /* Configure BW control field for the CSn */
- bw &= ~(SROMC_ATTR_MASK << (csn << 2));
- bw |= (attr << (csn << 2));
- writel(bw, S5P_SROM_BW);
- /* Verify SROMC settings */
- bw = __raw_readl(S5P_SROM_BW);
- DPRINTK("%s: new BW setting = 0x%08X\n", __func__, bw);
- }
- /**
- * sromc_config_access_timing
- * @csn: CSn number
- * @tm_cfg: pointer to an sromc_timing_cfg
- *
- * Configures SROMC access timing register
- *
- */
- static void sromc_config_access_timing(unsigned int csn,
- struct sromc_timing_cfg *tm_cfg)
- {
- void __iomem *bank_sfr = S5P_SROM_BC0 + (4 * csn);
- unsigned int bc = 0; /* Bank Control */
- bc = __raw_readl(bank_sfr);
- DPRINTK("%s: old BC%d setting = 0x%08X\n", __func__, csn, bc);
- /* Configure memory access timing for the CSn */
- bc = tm_cfg->tacs | tm_cfg->tcos | tm_cfg->tacc |
- tm_cfg->tcoh | tm_cfg->tcah | tm_cfg->tacp | tm_cfg->pmc;
- writel(bc, bank_sfr);
- /* Verify SROMC settings */
- bc = __raw_readl(bank_sfr);
- DPRINTK("%s: new BC%d setting = 0x%08X\n", __func__, csn, bc);
- }
- static struct sromc_bank_cfg tdmb_sromc_bank_cfg = {
- .csn = 0,
- .attr = 0,
- };
- static struct sromc_timing_cfg tdmb_sromc_timing_cfg = {
- .tacs = 0x0F << 28,
- .tcos = 0x02 << 24,
- .tacc = 0x1F << 16,
- .tcoh = 0x02 << 12,
- .tcah = 0x0F << 8,
- .tacp = 0x00 << 4,
- .pmc = 0x00 << 0,
- };
- unsigned long tdmb_get_if_handle(void)
- {
- return (unsigned long)v_addr_ebi_cs_base;
- }
- EXPORT_SYMBOL_GPL(tdmb_get_if_handle);
- static int tdmb_ebi_init(struct platform_device *pdev)
- {
- struct sromc_bank_cfg *bnk_cfg;
- struct sromc_timing_cfg *tm_cfg;
- if (sromc_enable(pdev) < 0) {
- printk(KERN_DEBUG "tdmb_dev_init sromc_enable fail\n");
- return -1;
- }
- if (sromc_config_demux_gpio(pdev) < 0) {
- printk(KERN_DEBUG "tdmb_dev_init sromc_config_demux_gpio fail\n");
- return -1;
- }
- bnk_cfg = &tdmb_sromc_bank_cfg;
- sromc_config_access_attr(bnk_cfg->csn, bnk_cfg->attr);
- tm_cfg = &tdmb_sromc_timing_cfg;
- sromc_config_access_timing(bnk_cfg->csn, tm_cfg);
- return 0;
- }
- static struct tdmb_ebi_dt_data *get_ebi_dt_pdata(struct device *dev)
- {
- struct tdmb_ebi_dt_data *pdata;
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- DPRINTK("%s : could not allocate memory for platform data\n", __func__);
- return NULL;
- }
- if (!of_property_read_u32(dev->of_node, "srom_cs_base", &pdata->cs_base))
- DPRINTK("%s - srom_cs_base : 0x%x\n", __func__, pdata->cs_base);
- else {
- DPRINTK("%s - cs_base missing\n", __func__);
- goto fail;
- }
- if (!of_property_read_u32(dev->of_node, "srom_mem_size", &pdata->mem_size))
- DPRINTK("%s - srom_mem_size : 0x%x\n", __func__, pdata->mem_size);
- else {
- DPRINTK("%s - mem_size missing\n", __func__);
- goto fail;
- }
- return pdata;
- fail:
- devm_kfree(dev, pdata);
- return NULL;
- }
- static int tdmb_sromc_remove(struct platform_device *pdev)
- {
- DPRINTK("tdmb_sromc_remove!\n");
- return 0;
- }
- static int tdmb_sromc_probe(struct platform_device *pdev)
- {
- if (pdev->dev.of_node) {
- ebi_dt_pdata = get_ebi_dt_pdata(&pdev->dev);
- if (!ebi_dt_pdata) {
- DPRINTK("%s : ebi_dt_pdata is NULL\n", __func__);
- return -1;
- }
- }
- if (tdmb_ebi_init(pdev) < 0) {
- DPRINTK("%s : tdmb_ebi_init error\n", __func__);
- return -1;
- }
- v_addr_ebi_cs_base = ioremap(ebi_dt_pdata->cs_base, ebi_dt_pdata->mem_size);
- DPRINTK("%s : v_addr_ebi_cs_base 0x%p\n", __func__, v_addr_ebi_cs_base);
- return 0;
- }
- static const struct of_device_id sromc_match_table[] = {
- {.compatible = "samsung,sromc"},
- {}
- };
- static struct platform_driver tdmb_ebi_driver = {
- .driver = {
- .name = "sromc",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(sromc_match_table),
- },
- .remove = tdmb_sromc_remove,
- };
- int __init tdmb_sromc_init(void)
- {
- return platform_driver_probe(&tdmb_ebi_driver, tdmb_sromc_probe);
- }
- module_init(tdmb_sromc_init);
- static void __exit tdmb_sromc_exit(void)
- {
- platform_driver_unregister(&tdmb_ebi_driver);
- }
- module_exit(tdmb_sromc_exit);
- MODULE_AUTHOR("Samsung");
- MODULE_DESCRIPTION("SROMC Driver");
- MODULE_LICENSE("GPL v2");
|