mcp-sa11x0.c (7017B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/drivers/mfd/mcp-sa11x0.c 4 * 5 * Copyright (C) 2001-2005 Russell King 6 * 7 * SA11x0 MCP (Multimedia Communications Port) driver. 8 * 9 * MCP read/write timeouts from Jordi Colomer, rehacked by rmk. 10 */ 11#include <linux/module.h> 12#include <linux/io.h> 13#include <linux/errno.h> 14#include <linux/kernel.h> 15#include <linux/delay.h> 16#include <linux/spinlock.h> 17#include <linux/platform_device.h> 18#include <linux/pm.h> 19#include <linux/mfd/mcp.h> 20 21#include <mach/hardware.h> 22#include <asm/mach-types.h> 23#include <linux/platform_data/mfd-mcp-sa11x0.h> 24 25#define DRIVER_NAME "sa11x0-mcp" 26 27struct mcp_sa11x0 { 28 void __iomem *base0; 29 void __iomem *base1; 30 u32 mccr0; 31 u32 mccr1; 32}; 33 34/* Register offsets */ 35#define MCCR0(m) ((m)->base0 + 0x00) 36#define MCDR0(m) ((m)->base0 + 0x08) 37#define MCDR1(m) ((m)->base0 + 0x0c) 38#define MCDR2(m) ((m)->base0 + 0x10) 39#define MCSR(m) ((m)->base0 + 0x18) 40#define MCCR1(m) ((m)->base1 + 0x00) 41 42#define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp)) 43 44static void 45mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) 46{ 47 struct mcp_sa11x0 *m = priv(mcp); 48 49 divisor /= 32; 50 51 m->mccr0 &= ~0x00007f00; 52 m->mccr0 |= divisor << 8; 53 writel_relaxed(m->mccr0, MCCR0(m)); 54} 55 56static void 57mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) 58{ 59 struct mcp_sa11x0 *m = priv(mcp); 60 61 divisor /= 32; 62 63 m->mccr0 &= ~0x0000007f; 64 m->mccr0 |= divisor; 65 writel_relaxed(m->mccr0, MCCR0(m)); 66} 67 68/* 69 * Write data to the device. The bit should be set after 3 subframe 70 * times (each frame is 64 clocks). We wait a maximum of 6 subframes. 71 * We really should try doing something more productive while we 72 * wait. 73 */ 74static void 75mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) 76{ 77 struct mcp_sa11x0 *m = priv(mcp); 78 int ret = -ETIME; 79 int i; 80 81 writel_relaxed(reg << 17 | MCDR2_Wr | (val & 0xffff), MCDR2(m)); 82 83 for (i = 0; i < 2; i++) { 84 udelay(mcp->rw_timeout); 85 if (readl_relaxed(MCSR(m)) & MCSR_CWC) { 86 ret = 0; 87 break; 88 } 89 } 90 91 if (ret < 0) 92 printk(KERN_WARNING "mcp: write timed out\n"); 93} 94 95/* 96 * Read data from the device. The bit should be set after 3 subframe 97 * times (each frame is 64 clocks). We wait a maximum of 6 subframes. 98 * We really should try doing something more productive while we 99 * wait. 100 */ 101static unsigned int 102mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) 103{ 104 struct mcp_sa11x0 *m = priv(mcp); 105 int ret = -ETIME; 106 int i; 107 108 writel_relaxed(reg << 17 | MCDR2_Rd, MCDR2(m)); 109 110 for (i = 0; i < 2; i++) { 111 udelay(mcp->rw_timeout); 112 if (readl_relaxed(MCSR(m)) & MCSR_CRC) { 113 ret = readl_relaxed(MCDR2(m)) & 0xffff; 114 break; 115 } 116 } 117 118 if (ret < 0) 119 printk(KERN_WARNING "mcp: read timed out\n"); 120 121 return ret; 122} 123 124static void mcp_sa11x0_enable(struct mcp *mcp) 125{ 126 struct mcp_sa11x0 *m = priv(mcp); 127 128 writel(-1, MCSR(m)); 129 m->mccr0 |= MCCR0_MCE; 130 writel_relaxed(m->mccr0, MCCR0(m)); 131} 132 133static void mcp_sa11x0_disable(struct mcp *mcp) 134{ 135 struct mcp_sa11x0 *m = priv(mcp); 136 137 m->mccr0 &= ~MCCR0_MCE; 138 writel_relaxed(m->mccr0, MCCR0(m)); 139} 140 141/* 142 * Our methods. 143 */ 144static struct mcp_ops mcp_sa11x0 = { 145 .set_telecom_divisor = mcp_sa11x0_set_telecom_divisor, 146 .set_audio_divisor = mcp_sa11x0_set_audio_divisor, 147 .reg_write = mcp_sa11x0_write, 148 .reg_read = mcp_sa11x0_read, 149 .enable = mcp_sa11x0_enable, 150 .disable = mcp_sa11x0_disable, 151}; 152 153static int mcp_sa11x0_probe(struct platform_device *dev) 154{ 155 struct mcp_plat_data *data = dev_get_platdata(&dev->dev); 156 struct resource *mem0, *mem1; 157 struct mcp_sa11x0 *m; 158 struct mcp *mcp; 159 int ret; 160 161 if (!data) 162 return -ENODEV; 163 164 mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0); 165 mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1); 166 if (!mem0 || !mem1) 167 return -ENXIO; 168 169 if (!request_mem_region(mem0->start, resource_size(mem0), 170 DRIVER_NAME)) { 171 ret = -EBUSY; 172 goto err_mem0; 173 } 174 175 if (!request_mem_region(mem1->start, resource_size(mem1), 176 DRIVER_NAME)) { 177 ret = -EBUSY; 178 goto err_mem1; 179 } 180 181 mcp = mcp_host_alloc(&dev->dev, sizeof(struct mcp_sa11x0)); 182 if (!mcp) { 183 ret = -ENOMEM; 184 goto err_alloc; 185 } 186 187 mcp->owner = THIS_MODULE; 188 mcp->ops = &mcp_sa11x0; 189 mcp->sclk_rate = data->sclk_rate; 190 191 m = priv(mcp); 192 m->mccr0 = data->mccr0 | 0x7f7f; 193 m->mccr1 = data->mccr1; 194 195 m->base0 = ioremap(mem0->start, resource_size(mem0)); 196 m->base1 = ioremap(mem1->start, resource_size(mem1)); 197 if (!m->base0 || !m->base1) { 198 ret = -ENOMEM; 199 goto err_ioremap; 200 } 201 202 platform_set_drvdata(dev, mcp); 203 204 /* 205 * Initialise device. Note that we initially 206 * set the sampling rate to minimum. 207 */ 208 writel_relaxed(-1, MCSR(m)); 209 writel_relaxed(m->mccr1, MCCR1(m)); 210 writel_relaxed(m->mccr0, MCCR0(m)); 211 212 /* 213 * Calculate the read/write timeout (us) from the bit clock 214 * rate. This is the period for 3 64-bit frames. Always 215 * round this time up. 216 */ 217 mcp->rw_timeout = DIV_ROUND_UP(64 * 3 * 1000000, mcp->sclk_rate); 218 219 ret = mcp_host_add(mcp, data->codec_pdata); 220 if (ret == 0) 221 return 0; 222 223 err_ioremap: 224 iounmap(m->base1); 225 iounmap(m->base0); 226 mcp_host_free(mcp); 227 err_alloc: 228 release_mem_region(mem1->start, resource_size(mem1)); 229 err_mem1: 230 release_mem_region(mem0->start, resource_size(mem0)); 231 err_mem0: 232 return ret; 233} 234 235static int mcp_sa11x0_remove(struct platform_device *dev) 236{ 237 struct mcp *mcp = platform_get_drvdata(dev); 238 struct mcp_sa11x0 *m = priv(mcp); 239 struct resource *mem0, *mem1; 240 241 if (m->mccr0 & MCCR0_MCE) 242 dev_warn(&dev->dev, 243 "device left active (missing disable call?)\n"); 244 245 mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0); 246 mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1); 247 248 mcp_host_del(mcp); 249 iounmap(m->base1); 250 iounmap(m->base0); 251 mcp_host_free(mcp); 252 release_mem_region(mem1->start, resource_size(mem1)); 253 release_mem_region(mem0->start, resource_size(mem0)); 254 255 return 0; 256} 257 258#ifdef CONFIG_PM_SLEEP 259static int mcp_sa11x0_suspend(struct device *dev) 260{ 261 struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev)); 262 263 if (m->mccr0 & MCCR0_MCE) 264 dev_warn(dev, "device left active (missing disable call?)\n"); 265 266 writel(m->mccr0 & ~MCCR0_MCE, MCCR0(m)); 267 268 return 0; 269} 270 271static int mcp_sa11x0_resume(struct device *dev) 272{ 273 struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev)); 274 275 writel_relaxed(m->mccr1, MCCR1(m)); 276 writel_relaxed(m->mccr0, MCCR0(m)); 277 278 return 0; 279} 280#endif 281 282static const struct dev_pm_ops mcp_sa11x0_pm_ops = { 283#ifdef CONFIG_PM_SLEEP 284 .suspend = mcp_sa11x0_suspend, 285 .freeze = mcp_sa11x0_suspend, 286 .poweroff = mcp_sa11x0_suspend, 287 .resume_noirq = mcp_sa11x0_resume, 288 .thaw_noirq = mcp_sa11x0_resume, 289 .restore_noirq = mcp_sa11x0_resume, 290#endif 291}; 292 293static struct platform_driver mcp_sa11x0_driver = { 294 .probe = mcp_sa11x0_probe, 295 .remove = mcp_sa11x0_remove, 296 .driver = { 297 .name = DRIVER_NAME, 298 .pm = &mcp_sa11x0_pm_ops, 299 }, 300}; 301 302/* 303 * This needs re-working 304 */ 305module_platform_driver(mcp_sa11x0_driver); 306 307MODULE_ALIAS("platform:" DRIVER_NAME); 308MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); 309MODULE_DESCRIPTION("SA11x0 multimedia communications port driver"); 310MODULE_LICENSE("GPL");