/* * drivers/stm/miphy_pcie_mp.c * * Copyright (c) 2010 STMicroelectronics Limited * Author: Srinivas.Kandagatla * * May be copied or modified under the terms of the GNU General Public * License Version 2.0 only. See linux/COPYING for more information. * * * Support for the UPort interface to MiPhy. */ #include #include #include #include #include #include #include #include #include "miphy.h" #define NAME "pcie-mp" struct pcie_mp_device{ struct stm_miphy_device miphy_dev; void __iomem *mp_base; void (*mp_select)(int port); struct miphy_if_ops *ops; }; static struct pcie_mp_device *mp_dev; static void stm_pcie_mp_register_write(int miphyselect, u8 address, u8 data) { BUG_ON(!mp_dev || !mp_dev->mp_select); mp_dev->mp_select(miphyselect); iowrite8(data, mp_dev->mp_base + address); } static u8 stm_pcie_mp_register_read(int miphyselect, u8 address) { u8 data; BUG_ON(!mp_dev || !mp_dev->mp_select); mp_dev->mp_select(miphyselect); data = ioread8(mp_dev->mp_base + address); return data; } static const struct miphy_if_ops stm_miphy_mp_ops = { .reg_write = stm_pcie_mp_register_write, .reg_read = stm_pcie_mp_register_read, }; static int __init pcie_mp_probe(struct platform_device *pdev) { struct resource *res; struct stm_plat_pcie_mp_data *data = (struct stm_plat_pcie_mp_data *)pdev->dev.platform_data; int result; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mp_dev = kzalloc(sizeof(struct pcie_mp_device), GFP_KERNEL); if (!mp_dev) return -ENOMEM; if (!devm_request_mem_region(&pdev->dev, res->start, res->end - res->start, "pcie-mp")) { printk(KERN_ERR NAME " Request mem 0x%x region failed\n", res->start); return -ENOMEM; } mp_dev->mp_base = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res)); mp_dev->mp_select = data->mp_select; if (!mp_dev->mp_base) return -ENOMEM; result = miphy_if_register(&mp_dev->miphy_dev, UPORT_IF, data->miphy_first, data->miphy_count, data->miphy_modes, &pdev->dev, &stm_miphy_mp_ops); if (result) { printk(KERN_ERR "Unable to Register uPort MiPHY device\n"); return result; } return 0; } static int pcie_mp_remove(struct platform_device *pdev) { miphy_if_unregister(&mp_dev->miphy_dev); kfree(mp_dev->ops); kfree(mp_dev); mp_dev = NULL; return 0; } static struct platform_driver pcie_mp_driver = { .driver.name = NAME, .driver.owner = THIS_MODULE, .probe = pcie_mp_probe, .remove = pcie_mp_remove, }; static int __init pcie_mp_init(void) { return platform_driver_register(&pcie_mp_driver); } postcore_initcall(pcie_mp_init); MODULE_AUTHOR("Srinivas.Kandagatla "); MODULE_DESCRIPTION("STM PCIE-UPort driver"); MODULE_LICENSE("GPL");