467 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Based on sound/arm/pxa2xx-ac97.c and sound/soc/pxa/pxa2xx-ac97.c4 * which contain:5 *6 * Author: Nicolas Pitre7 * Created: Dec 02, 20048 * Copyright: MontaVista Software Inc.9 */10 11#include <linux/kernel.h>12#include <linux/platform_device.h>13#include <linux/interrupt.h>14#include <linux/clk.h>15#include <linux/delay.h>16#include <linux/module.h>17#include <linux/io.h>18#include <linux/gpio.h>19#include <linux/of_gpio.h>20#include <linux/soc/pxa/cpu.h>21 22#include <sound/pxa2xx-lib.h>23 24#include <linux/platform_data/asoc-pxa.h>25 26#include "pxa2xx-ac97-regs.h"27 28static DEFINE_MUTEX(car_mutex);29static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);30static volatile long gsr_bits;31static struct clk *ac97_clk;32static struct clk *ac97conf_clk;33static int reset_gpio;34static void __iomem *ac97_reg_base;35 36/*37 * Beware PXA27x bugs:38 *39 * o Slot 12 read from modem space will hang controller.40 * o CDONE, SDONE interrupt fails after any slot 12 IO.41 *42 * We therefore have an hybrid approach for waiting on SDONE (interrupt or43 * 1 jiffy timeout if interrupt never comes).44 */45 46int pxa2xx_ac97_read(int slot, unsigned short reg)47{48 int val = -ENODEV;49 u32 __iomem *reg_addr;50 51 if (slot > 0)52 return -ENODEV;53 54 mutex_lock(&car_mutex);55 56 /* set up primary or secondary codec space */57 if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)58 reg_addr = ac97_reg_base +59 (slot ? SMC_REG_BASE : PMC_REG_BASE);60 else61 reg_addr = ac97_reg_base +62 (slot ? SAC_REG_BASE : PAC_REG_BASE);63 reg_addr += (reg >> 1);64 65 /* start read access across the ac97 link */66 writel(GSR_CDONE | GSR_SDONE, ac97_reg_base + GSR);67 gsr_bits = 0;68 val = (readl(reg_addr) & 0xffff);69 if (reg == AC97_GPIO_STATUS)70 goto out;71 if (wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE, 1) <= 0 &&72 !((readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE)) {73 printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",74 __func__, reg, readl(ac97_reg_base + GSR) | gsr_bits);75 val = -ETIMEDOUT;76 goto out;77 }78 79 /* valid data now */80 writel(GSR_CDONE | GSR_SDONE, ac97_reg_base + GSR);81 gsr_bits = 0;82 val = (readl(reg_addr) & 0xffff);83 /* but we've just started another cycle... */84 wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE, 1);85 86out: mutex_unlock(&car_mutex);87 return val;88}89EXPORT_SYMBOL_GPL(pxa2xx_ac97_read);90 91int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val)92{93 u32 __iomem *reg_addr;94 int ret = 0;95 96 mutex_lock(&car_mutex);97 98 /* set up primary or secondary codec space */99 if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)100 reg_addr = ac97_reg_base +101 (slot ? SMC_REG_BASE : PMC_REG_BASE);102 else103 reg_addr = ac97_reg_base +104 (slot ? SAC_REG_BASE : PAC_REG_BASE);105 reg_addr += (reg >> 1);106 107 writel(GSR_CDONE | GSR_SDONE, ac97_reg_base + GSR);108 gsr_bits = 0;109 writel(val, reg_addr);110 if (wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_CDONE, 1) <= 0 &&111 !((readl(ac97_reg_base + GSR) | gsr_bits) & GSR_CDONE)) {112 printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",113 __func__, reg, readl(ac97_reg_base + GSR) | gsr_bits);114 ret = -EIO;115 }116 117 mutex_unlock(&car_mutex);118 return ret;119}120EXPORT_SYMBOL_GPL(pxa2xx_ac97_write);121 122#ifdef CONFIG_PXA25x123static inline void pxa_ac97_warm_pxa25x(void)124{125 gsr_bits = 0;126 127 writel(readl(ac97_reg_base + GCR) | (GCR_WARM_RST), ac97_reg_base + GCR);128}129 130static inline void pxa_ac97_cold_pxa25x(void)131{132 writel(readl(ac97_reg_base + GCR) & ( GCR_COLD_RST), ac97_reg_base + GCR); /* clear everything but nCRST */133 writel(readl(ac97_reg_base + GCR) & (~GCR_COLD_RST), ac97_reg_base + GCR); /* then assert nCRST */134 135 gsr_bits = 0;136 137 writel(GCR_COLD_RST, ac97_reg_base + GCR);138}139#endif140 141#ifdef CONFIG_PXA27x142static inline void pxa_ac97_warm_pxa27x(void)143{144 gsr_bits = 0;145 146 /* warm reset broken on Bulverde, so manually keep AC97 reset high */147 pxa27x_configure_ac97reset(reset_gpio, true);148 udelay(10);149 writel(readl(ac97_reg_base + GCR) | (GCR_WARM_RST), ac97_reg_base + GCR);150 pxa27x_configure_ac97reset(reset_gpio, false);151 udelay(500);152}153 154static inline void pxa_ac97_cold_pxa27x(void)155{156 writel(readl(ac97_reg_base + GCR) & ( GCR_COLD_RST), ac97_reg_base + GCR); /* clear everything but nCRST */157 writel(readl(ac97_reg_base + GCR) & (~GCR_COLD_RST), ac97_reg_base + GCR); /* then assert nCRST */158 159 gsr_bits = 0;160 161 /* PXA27x Developers Manual section 13.5.2.2.1 */162 clk_prepare_enable(ac97conf_clk);163 udelay(5);164 clk_disable_unprepare(ac97conf_clk);165 writel(GCR_COLD_RST | GCR_WARM_RST, ac97_reg_base + GCR);166}167#endif168 169#ifdef CONFIG_PXA3xx170static inline void pxa_ac97_warm_pxa3xx(void)171{172 gsr_bits = 0;173 174 /* Can't use interrupts */175 writel(readl(ac97_reg_base + GCR) | (GCR_WARM_RST), ac97_reg_base + GCR);176}177 178static inline void pxa_ac97_cold_pxa3xx(void)179{180 /* Hold CLKBPB for 100us */181 writel(0, ac97_reg_base + GCR);182 writel(GCR_CLKBPB, ac97_reg_base + GCR);183 udelay(100);184 writel(0, ac97_reg_base + GCR);185 186 writel(readl(ac97_reg_base + GCR) & ( GCR_COLD_RST), ac97_reg_base + GCR); /* clear everything but nCRST */187 writel(readl(ac97_reg_base + GCR) & (~GCR_COLD_RST), ac97_reg_base + GCR); /* then assert nCRST */188 189 gsr_bits = 0;190 191 /* Can't use interrupts on PXA3xx */192 writel(readl(ac97_reg_base + GCR) & (~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN)), ac97_reg_base + GCR);193 194 writel(GCR_WARM_RST | GCR_COLD_RST, ac97_reg_base + GCR);195}196#endif197 198bool pxa2xx_ac97_try_warm_reset(void)199{200 unsigned long gsr;201 unsigned int timeout = 100;202 203#ifdef CONFIG_PXA25x204 if (cpu_is_pxa25x())205 pxa_ac97_warm_pxa25x();206 else207#endif208#ifdef CONFIG_PXA27x209 if (cpu_is_pxa27x())210 pxa_ac97_warm_pxa27x();211 else212#endif213#ifdef CONFIG_PXA3xx214 if (cpu_is_pxa3xx())215 pxa_ac97_warm_pxa3xx();216 else217#endif218 snd_BUG();219 220 while (!((readl(ac97_reg_base + GSR) | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)221 mdelay(1);222 223 gsr = readl(ac97_reg_base + GSR) | gsr_bits;224 if (!(gsr & (GSR_PCR | GSR_SCR))) {225 printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",226 __func__, gsr);227 228 return false;229 }230 231 return true;232}233EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);234 235bool pxa2xx_ac97_try_cold_reset(void)236{237 unsigned long gsr;238 unsigned int timeout = 1000;239 240#ifdef CONFIG_PXA25x241 if (cpu_is_pxa25x())242 pxa_ac97_cold_pxa25x();243 else244#endif245#ifdef CONFIG_PXA27x246 if (cpu_is_pxa27x())247 pxa_ac97_cold_pxa27x();248 else249#endif250#ifdef CONFIG_PXA3xx251 if (cpu_is_pxa3xx())252 pxa_ac97_cold_pxa3xx();253 else254#endif255 snd_BUG();256 257 while (!((readl(ac97_reg_base + GSR) | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)258 mdelay(1);259 260 gsr = readl(ac97_reg_base + GSR) | gsr_bits;261 if (!(gsr & (GSR_PCR | GSR_SCR))) {262 printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",263 __func__, gsr);264 265 return false;266 }267 268 return true;269}270EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_cold_reset);271 272 273void pxa2xx_ac97_finish_reset(void)274{275 u32 gcr = readl(ac97_reg_base + GCR);276 gcr &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);277 gcr |= GCR_SDONE_IE|GCR_CDONE_IE;278 writel(gcr, ac97_reg_base + GCR);279}280EXPORT_SYMBOL_GPL(pxa2xx_ac97_finish_reset);281 282static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)283{284 long status;285 286 status = readl(ac97_reg_base + GSR);287 if (status) {288 writel(status, ac97_reg_base + GSR);289 gsr_bits |= status;290 wake_up(&gsr_wq);291 292 /* Although we don't use those we still need to clear them293 since they tend to spuriously trigger when MMC is used294 (hardware bug? go figure)... */295 if (cpu_is_pxa27x()) {296 writel(MISR_EOC, ac97_reg_base + MISR);297 writel(PISR_EOC, ac97_reg_base + PISR);298 writel(MCSR_EOC, ac97_reg_base + MCSR);299 }300 301 return IRQ_HANDLED;302 }303 304 return IRQ_NONE;305}306 307#ifdef CONFIG_PM308int pxa2xx_ac97_hw_suspend(void)309{310 writel(readl(ac97_reg_base + GCR) | (GCR_ACLINK_OFF), ac97_reg_base + GCR);311 clk_disable_unprepare(ac97_clk);312 return 0;313}314EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);315 316int pxa2xx_ac97_hw_resume(void)317{318 clk_prepare_enable(ac97_clk);319 return 0;320}321EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);322#endif323 324int pxa2xx_ac97_hw_probe(struct platform_device *dev)325{326 int ret;327 int irq;328 pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;329 330 ac97_reg_base = devm_platform_ioremap_resource(dev, 0);331 if (IS_ERR(ac97_reg_base)) {332 dev_err(&dev->dev, "Missing MMIO resource\n");333 return PTR_ERR(ac97_reg_base);334 }335 336 if (pdata) {337 switch (pdata->reset_gpio) {338 case 95:339 case 113:340 reset_gpio = pdata->reset_gpio;341 break;342 case 0:343 reset_gpio = 113;344 break;345 case -1:346 break;347 default:348 dev_err(&dev->dev, "Invalid reset GPIO %d\n",349 pdata->reset_gpio);350 }351 } else if (!pdata && dev->dev.of_node) {352 pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);353 if (!pdata)354 return -ENOMEM;355 pdata->reset_gpio = of_get_named_gpio(dev->dev.of_node,356 "reset-gpios", 0);357 if (pdata->reset_gpio == -ENOENT)358 pdata->reset_gpio = -1;359 else if (pdata->reset_gpio < 0)360 return pdata->reset_gpio;361 reset_gpio = pdata->reset_gpio;362 } else {363 if (cpu_is_pxa27x())364 reset_gpio = 113;365 }366 367 if (cpu_is_pxa27x()) {368 /*369 * This gpio is needed for a work-around to a bug in the ac97370 * controller during warm reset. The direction and level is set371 * here so that it is an output driven high when switching from372 * AC97_nRESET alt function to generic gpio.373 */374 ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH,375 "pxa27x ac97 reset");376 if (ret < 0) {377 pr_err("%s: gpio_request_one() failed: %d\n",378 __func__, ret);379 goto err_conf;380 }381 pxa27x_configure_ac97reset(reset_gpio, false);382 383 ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");384 if (IS_ERR(ac97conf_clk)) {385 ret = PTR_ERR(ac97conf_clk);386 ac97conf_clk = NULL;387 goto err_conf;388 }389 }390 391 ac97_clk = clk_get(&dev->dev, "AC97CLK");392 if (IS_ERR(ac97_clk)) {393 ret = PTR_ERR(ac97_clk);394 ac97_clk = NULL;395 goto err_clk;396 }397 398 ret = clk_prepare_enable(ac97_clk);399 if (ret)400 goto err_clk2;401 402 irq = platform_get_irq(dev, 0);403 if (irq < 0) {404 ret = irq;405 goto err_irq;406 }407 408 ret = request_irq(irq, pxa2xx_ac97_irq, 0, "AC97", NULL);409 if (ret < 0)410 goto err_irq;411 412 return 0;413 414err_irq:415 writel(readl(ac97_reg_base + GCR) | (GCR_ACLINK_OFF), ac97_reg_base + GCR);416err_clk2:417 clk_put(ac97_clk);418 ac97_clk = NULL;419err_clk:420 if (ac97conf_clk) {421 clk_put(ac97conf_clk);422 ac97conf_clk = NULL;423 }424err_conf:425 return ret;426}427EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);428 429void pxa2xx_ac97_hw_remove(struct platform_device *dev)430{431 if (cpu_is_pxa27x())432 gpio_free(reset_gpio);433 writel(readl(ac97_reg_base + GCR) | (GCR_ACLINK_OFF), ac97_reg_base + GCR);434 free_irq(platform_get_irq(dev, 0), NULL);435 if (ac97conf_clk) {436 clk_put(ac97conf_clk);437 ac97conf_clk = NULL;438 }439 clk_disable_unprepare(ac97_clk);440 clk_put(ac97_clk);441 ac97_clk = NULL;442}443EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_remove);444 445u32 pxa2xx_ac97_read_modr(void)446{447 if (!ac97_reg_base)448 return 0;449 450 return readl(ac97_reg_base + MODR);451}452EXPORT_SYMBOL_GPL(pxa2xx_ac97_read_modr);453 454u32 pxa2xx_ac97_read_misr(void)455{456 if (!ac97_reg_base)457 return 0;458 459 return readl(ac97_reg_base + MISR);460}461EXPORT_SYMBOL_GPL(pxa2xx_ac97_read_misr);462 463MODULE_AUTHOR("Nicolas Pitre");464MODULE_DESCRIPTION("Intel/Marvell PXA sound library");465MODULE_LICENSE("GPL");466 467