diff --git a/MAINTAINERS b/MAINTAINERS index 323d86be050e..168b33dfdd73 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13755,6 +13755,8 @@ F: drivers/amlogic/led/* AMLOGIC JTAG DRIVER SUPPORT M: Bo Yang F: drivers/amlogic/jtag/* +X: include/linux/amlogic/mmc_notify.h + AMLOGIC AMLVIDEO DRIVER M: Guosong Zhou diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index d7b3405b3263..b040ba1f74cd 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -226,10 +226,16 @@ jtag { compatible = "amlogic, jtag"; - status = "disabled"; - pinctrl-names = "jtag_apao_pins", "jtag_apee_pins"; - pinctrl-0 = <&jtag_apao_pins>; - pinctrl-1 = <&jtag_apee_pins>; + status = "okay"; + select = "apao"; /* disable/apao/apee */ + jtagao-gpios = <&gpio GPIOH_6 0 + &gpio GPIOH_7 0 + &gpio GPIOH_8 0 + &gpio GPIOH_9 0>; + jtagee-gpios = <&gpio CARD_0 0 + &gpio CARD_1 0 + &gpio CARD_2 0 + &gpio CARD_3 0>; }; mailbox: mhu@c883c400 { @@ -620,26 +626,6 @@ }; }; - jtag_apao_pins:jtag_apao_pin { - mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; - }; - }; - - jtag_apee_pins:jtag_apee_pin { - mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; - }; - }; - a_uart_pins:a_uart { mux { groups = "uart_tx_a", diff --git a/drivers/amlogic/jtag/meson_jtag.c b/drivers/amlogic/jtag/meson_jtag.c index f0f845796d29..97d38bd0098f 100644 --- a/drivers/amlogic/jtag/meson_jtag.c +++ b/drivers/amlogic/jtag/meson_jtag.c @@ -41,21 +41,27 @@ #include #include -#include #include "meson_jtag.h" #define AML_JTAG_NAME "jtag" +/* store the jtag select globaly */ +static int global_select = AMLOGIC_JTAG_DISABLE; + +/* whether the jtag select is setup by the boot param + * jtag select is setup by the boot prior to device tree. + */ static bool jtag_select_setup; +/* store the params that are setup by the boot param */ static int jtag_select = AMLOGIC_JTAG_DISABLE; static int jtag_cluster = CLUSTER_DISABLE; bool is_jtag_disable(void) { - if (jtag_select == AMLOGIC_JTAG_DISABLE) + if (global_select == AMLOGIC_JTAG_DISABLE) return true; else return false; @@ -64,7 +70,7 @@ EXPORT_SYMBOL(is_jtag_disable); bool is_jtag_apao(void) { - if (jtag_select == AMLOGIC_JTAG_AO) + if (global_select == AMLOGIC_JTAG_APAO) return true; else return false; @@ -73,13 +79,26 @@ EXPORT_SYMBOL(is_jtag_apao); bool is_jtag_apee(void) { - if (jtag_select == AMLOGIC_JTAG_EE) + if (global_select == AMLOGIC_JTAG_APEE) return true; else return false; } EXPORT_SYMBOL(is_jtag_apee); +static inline char *select_to_name(int select) +{ + switch (select) { + case AMLOGIC_JTAG_APAO: + return "apao"; + case AMLOGIC_JTAG_APEE: + return "apee"; + default: + return "disable"; + } + +} + static void aml_jtag_option_parse(struct aml_jtag_dev *jdev, const char *s) { char *cluster; @@ -89,14 +108,11 @@ static void aml_jtag_option_parse(struct aml_jtag_dev *jdev, const char *s) if (!strncmp(s, "disable", 7)) jdev->select = AMLOGIC_JTAG_DISABLE; else if (!strncmp(s, "apao", 4)) - jdev->select = AMLOGIC_JTAG_AO; + jdev->select = AMLOGIC_JTAG_APAO; else if (!strncmp(s, "apee", 4)) - jdev->select = AMLOGIC_JTAG_EE; + jdev->select = AMLOGIC_JTAG_APEE; else - pr_info("unknown select: %s", s); - - jtag_select = jdev->select; - pr_info("jtag select %d\n", jdev->select); + pr_err("unknown select: %s", s); cluster = strchr(s, ','); if (cluster != NULL) { @@ -111,9 +127,6 @@ static void aml_jtag_option_parse(struct aml_jtag_dev *jdev, const char *s) } else { jdev->cluster = CLUSTER_DISABLE; } - - jtag_cluster = jdev->cluster; - pr_info("cluster index %d\n", jdev->cluster); } static int __init setup_jtag(char *p) @@ -127,13 +140,13 @@ static int __init setup_jtag(char *p) if (!strncmp(p, "disable", 7)) jtag_select = AMLOGIC_JTAG_DISABLE; else if (!strncmp(p, "apao", 4)) - jtag_select = AMLOGIC_JTAG_AO; + jtag_select = AMLOGIC_JTAG_APAO; else if (!strncmp(p, "apee", 4)) - jtag_select = AMLOGIC_JTAG_EE; + jtag_select = AMLOGIC_JTAG_APEE; else jtag_select = AMLOGIC_JTAG_DISABLE; - pr_info("jtag select %d\n", jtag_select); + pr_info("jtag select %s\n", select_to_name(jtag_select)); cluster = strchr(p, ','); if (cluster != NULL) { @@ -162,81 +175,95 @@ __setup("jtag=", setup_jtag); /* - * clean other pinmux except jtag register. - * jtag register will be setup by aml_set_jtag_state(). + * request gpios for jtag apao. * - *@return: 0 success, other failed + * @return: 0 success, other failed * */ -static int aml_jtag_pinmux_apao(struct platform_device *pdev) +static int aml_jtag_apao_request_gpios(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; + struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); + const unsigned int *gpios = jdev->ao_gpios; - int count, i, ret; - int gpio; + int ngpio, i, ret; - count = of_gpio_named_count(np, "jtagao-gpios"); + ngpio = jdev->ao_ngpios; - for (i = 0; i < count; i++) { - gpio = of_get_named_gpio(dev->of_node, "jtagao-gpios", i); - if (!gpio_is_valid(gpio)) { - dev_err(dev, "gpio %d is not valid", gpio); - return -ENOENT; - } - - ret = devm_gpio_request(dev, gpio, "jtagao"); + for (i = 0; i < ngpio; i++) { + ret = devm_gpio_request(dev, gpios[i], "apao"); if (ret) { - dev_err(dev, "can't request gpio %d", gpio); + pr_err("can't request gpio %d", gpios[i]); return -ENOENT; } + pr_info("request gpio %d for apao\n", gpios[i]); } return 0; } -static int aml_jtag_pinmux_apee(struct platform_device *pdev) +static int aml_jtag_apao_free_gpios(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; + struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); + const unsigned int *gpios = jdev->ao_gpios; - int count, i, ret; - int gpio; + int ngpio, i; - count = of_gpio_named_count(np, "jtagee-gpios"); + ngpio = jdev->ao_ngpios; - for (i = 0; i < count; i++) { - gpio = of_get_named_gpio(dev->of_node, "jtagee-gpios", i); - if (!gpio_is_valid(gpio)) { - dev_err(dev, "gpio %d is not valid", gpio); - return -ENOENT; - } - - ret = devm_gpio_request(dev, gpio, "jtagee"); - if (ret) { - dev_err(dev, "can't request gpio %d", gpio); - return -ENOENT; - } - } + for (i = 0; i < ngpio; i++) + devm_gpio_free(dev, gpios[i]); return 0; } -static void aml_jtag_pinctrl(struct aml_jtag_dev *jdev) +/* + * request gpios for jtag apee. + * + * @return: 0 success, other failed + * + */ +static int aml_jtag_apee_request_gpios(struct platform_device *pdev) { - switch (jdev->select) { - case AMLOGIC_JTAG_AO: - aml_jtag_pinmux_apao(jdev->pdev); - break; - case AMLOGIC_JTAG_EE: - aml_jtag_pinmux_apee(jdev->pdev); - break; - default: - break; + struct device *dev = &pdev->dev; + struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); + const unsigned int *gpios = jdev->ee_gpios; + + int ngpio, i, ret; + + ngpio = jdev->ee_ngpios; + + for (i = 0; i < ngpio; i++) { + ret = devm_gpio_request(dev, gpios[i], "apee"); + if (ret) { + pr_err("can't request gpio %d", gpios[i]); + return -ENOENT; + } + pr_info("request gpio %d for apee\n", gpios[i]); } + + return 0; } +static int aml_jtag_apee_free_gpios(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); + const unsigned int *gpios = jdev->ee_gpios; + + int ngpio, i; + + ngpio = jdev->ee_ngpios; + + for (i = 0; i < ngpio; i++) + devm_gpio_free(dev, gpios[i]); + + return 0; +} + + #ifdef CONFIG_MACH_MESON8B static int aml_jtag_select(struct platform_device *pdev) @@ -249,7 +276,7 @@ static int aml_jtag_select(struct platform_device *pdev) jdev->base = of_iomap(np, 0); if (!jdev->base) { - dev_err(dev, "failed to iomap regs"); + pr_err("failed to iomap regs"); return -ENODEV; } @@ -257,13 +284,13 @@ static int aml_jtag_select(struct platform_device *pdev) case AMLOGIC_JTAG_DISABLE: writel_relaxed(0x0, jdev->base); break; - case AMLOGIC_JTAG_AO: + case AMLOGIC_JTAG_APAO: val = readl_relaxed(jdev->base); val &= ~0x3FF; val |= (2 << 0) | (1 << 8); writel_relaxed(val, jdev->base); break; - case AMLOGIC_JTAG_EE: + case AMLOGIC_JTAG_APEE: val = readl_relaxed(jdev->base); val &= ~0x3FF; val |= (2 << 4) | (2 << 8); @@ -312,15 +339,19 @@ void aml_set_jtag_state(unsigned int state, unsigned int select) static int aml_jtag_select(struct platform_device *pdev) { struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); - unsigned int sel = jdev->select; + unsigned int select = jdev->select; + unsigned int state = AMLOGIC_JTAG_STATE_OFF; + + if (select != AMLOGIC_JTAG_DISABLE) + state = AMLOGIC_JTAG_STATE_ON; if (jdev->cluster != CLUSTER_DISABLE) - sel |= jdev->cluster << CLUSTER_BIT; + select |= jdev->cluster << CLUSTER_BIT; - pr_info("set state %u\n", sel); + pr_info("set state %u\n", select); set_cpus_allowed_ptr(current, cpumask_of(0)); - aml_set_jtag_state(AMLOGIC_JTAG_STATE_ON, sel); + aml_set_jtag_state(AMLOGIC_JTAG_STATE_ON, select); set_cpus_allowed_ptr(current, cpu_all_mask); return 0; @@ -330,8 +361,41 @@ static int aml_jtag_select(struct platform_device *pdev) static void aml_jtag_setup(struct aml_jtag_dev *jdev) { - aml_jtag_pinctrl(jdev); + struct platform_device *pdev = jdev->pdev; + unsigned int old_select = jdev->old_select; + unsigned int select = jdev->select; + + if (old_select == select) + return; + + /* free gpios */ + switch (old_select) { + case AMLOGIC_JTAG_APAO: + aml_jtag_apao_free_gpios(pdev); + break; + case AMLOGIC_JTAG_APEE: + aml_jtag_apee_free_gpios(pdev); + break; + default: + break; + } + + /* free gpios */ + switch (select) { + case AMLOGIC_JTAG_APAO: + aml_jtag_apao_request_gpios(pdev); + break; + case AMLOGIC_JTAG_APEE: + aml_jtag_apee_request_gpios(pdev); + break; + default: + break; + } + aml_jtag_select(jdev->pdev); + + jdev->old_select = select; + } static ssize_t jtag_select_show(struct class *cls, @@ -339,6 +403,8 @@ static ssize_t jtag_select_show(struct class *cls, { unsigned int len = 0; + len += sprintf(buf + len, "current select: %s\n\n", + select_to_name(global_select)); len += sprintf(buf + len, "usage:\n"); len += sprintf(buf + len, " echo [apao|apee] > select\n"); len += sprintf(buf + len, " echo [apao|apee]{,[0|1]} > select\n"); @@ -354,6 +420,10 @@ static ssize_t jtag_select_store(struct class *cls, jdev = container_of(cls, struct aml_jtag_dev, cls); aml_jtag_option_parse(jdev, buffer); + + /* save to global */ + global_select = jdev->select; + aml_jtag_setup(jdev); return count; @@ -365,52 +435,63 @@ static struct class_attribute aml_jtag_attrs[] = { }; -static int jtag_notify_callback(struct notifier_block *block, - unsigned long event, void *data) -{ - struct aml_jtag_dev *jdev; - - jdev = container_of(block, struct aml_jtag_dev, notifier); - - - /* @todo need mmc driver to implement notify calling */ - pr_info("%s %lu\n", __func__, event); - switch (event) { - case MMC_EVENT_JTAG_IN: - jdev->select = AMLOGIC_JTAG_EE; - jtag_select = jdev->select; - break; - - case MMC_EVENT_JTAG_OUT: - jdev->select = AMLOGIC_JTAG_AO; - jtag_select = jdev->select; - break; - - default: - return NOTIFY_DONE; - } - - aml_jtag_setup(jdev); - - return NOTIFY_OK; -} - - static int aml_jtag_dt_parse(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); const char *tmp; - int ret; - /* if jtag= param is setup, set select with jtag= param */ - if (jtag_select_setup) { - jdev->select = jtag_select; - jdev->cluster = jtag_cluster; - return 0; + int ao_ngpios, ee_ngpios; + unsigned int *ao_gpios, *ee_gpios; + int ret, i, gpio; + + + ao_ngpios = of_gpio_named_count(np, "jtagao-gpios"); + if (ao_ngpios <= 0) { + pr_err("ao gpios not specified\n"); + return -EINVAL; } + ee_ngpios = of_gpio_named_count(np, "jtagee-gpios"); + if (ee_ngpios <= 0) { + pr_err("ee gpios not specified\n"); + return -EINVAL; + } + + jdev->ao_ngpios = ao_ngpios; + jdev->ee_ngpios = ee_ngpios; + + ao_gpios = devm_kzalloc(dev, sizeof(unsigned int) * ao_ngpios, + GFP_KERNEL); + ee_gpios = devm_kzalloc(dev, sizeof(unsigned int) * ee_ngpios, + GFP_KERNEL); + if (!ao_gpios || !ee_gpios) { + pr_err("failed to allocate memory for gpios\n"); + return -ENOMEM; + } + + for (i = 0; i < ao_ngpios; i++) { + gpio = of_get_named_gpio(dev->of_node, "jtagao-gpios", i); + if (!gpio_is_valid(gpio)) { + pr_err("gpio %d is not valid", gpio); + return -EINVAL; + } + ao_gpios[i] = gpio; + } + + for (i = 0; i < ee_ngpios; i++) { + gpio = of_get_named_gpio(dev->of_node, "jtagee-gpios", i); + if (!gpio_is_valid(gpio)) { + pr_err("gpio %d is not valid", gpio); + return -EINVAL; + } + ee_gpios[i] = gpio; + } + + jdev->ao_gpios = ao_gpios; + jdev->ee_gpios = ee_gpios; + /* otherwise set select with dt */ ret = of_property_read_string(np, "select", &tmp); if (ret < 0) { @@ -422,11 +503,11 @@ static int aml_jtag_dt_parse(struct platform_device *pdev) if (!strcmp(tmp, "disable")) jdev->select = AMLOGIC_JTAG_DISABLE; else if (!strcmp(tmp, "apao")) - jdev->select = AMLOGIC_JTAG_AO; + jdev->select = AMLOGIC_JTAG_APAO; else if (!strcmp(tmp, "apee")) - jdev->select = AMLOGIC_JTAG_EE; + jdev->select = AMLOGIC_JTAG_APEE; else - dev_warn(dev, "unknown select: %s", tmp); + pr_err("unknown select: %s", tmp); return 0; } @@ -445,7 +526,20 @@ static int aml_jtag_probe(struct platform_device *pdev) jdev->pdev = pdev; platform_set_drvdata(pdev, jdev); - aml_jtag_dt_parse(pdev); + ret = aml_jtag_dt_parse(pdev); + if (ret) + return -EINVAL; + + jdev->old_select = AMLOGIC_JTAG_DISABLE; + /* if jtag= param is setup, use select with jtag= param */ + if (jtag_select_setup) { + jdev->select = jtag_select; + jdev->cluster = jtag_cluster; + pr_info("select is replaced by boot param\n"); + } + + /* save to global */ + global_select = jdev->select; /* create class attributes */ jdev->cls.name = AML_JTAG_NAME; @@ -453,10 +547,6 @@ static int aml_jtag_probe(struct platform_device *pdev) jdev->cls.class_attrs = aml_jtag_attrs; class_register(&jdev->cls); - /* register mmc notify */ - jdev->notifier.notifier_call = jtag_notify_callback; - ret = mmc_register_client(&jdev->notifier); - /* setup jtag */ aml_jtag_setup(jdev); diff --git a/drivers/amlogic/jtag/meson_jtag.h b/drivers/amlogic/jtag/meson_jtag.h index 771588fdbb39..41713a601351 100644 --- a/drivers/amlogic/jtag/meson_jtag.h +++ b/drivers/amlogic/jtag/meson_jtag.h @@ -25,7 +25,6 @@ #define CLUSTER_BIT 2 #define CLUSTER_DISABLE (-1) - struct aml_jtag_dev { struct platform_device *pdev; struct class cls; @@ -36,8 +35,16 @@ struct aml_jtag_dev { struct notifier_block notifier; + unsigned int old_select; unsigned int select; unsigned int cluster; + + const unsigned int *ao_gpios; + const unsigned int *ee_gpios; + + int ao_ngpios; + int ee_ngpios; + }; #endif diff --git a/include/linux/amlogic/jtag.h b/include/linux/amlogic/jtag.h index bcf3c57e1427..8497f5c2bb32 100644 --- a/include/linux/amlogic/jtag.h +++ b/include/linux/amlogic/jtag.h @@ -24,8 +24,8 @@ #define AMLOGIC_JTAG_STATE_OFF 1 #define AMLOGIC_JTAG_DISABLE (-1) -#define AMLOGIC_JTAG_AO 2 -#define AMLOGIC_JTAG_EE 3 +#define AMLOGIC_JTAG_APAO 2 +#define AMLOGIC_JTAG_APEE 3 #define AMLOGIC_JTAG_ON 0x82000040 #define AMLOGIC_JTAG_OFF 0x82000041 @@ -41,5 +41,4 @@ static inline bool is_jtag_apao(void) { return false; } static inline bool is_jtag_apee(void) { return false; } #endif - #endif diff --git a/include/linux/amlogic/mmc_notify.h b/include/linux/amlogic/mmc_notify.h deleted file mode 100644 index 9bdfd304dcf0..000000000000 --- a/include/linux/amlogic/mmc_notify.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * include/linux/amlogic/mmc_notify.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - */ - -#ifndef __LINUX_AMLOGIC_MMC_NOTIFY_H -#define __LINUX_AMLOGIC_MMC_NOTIFY_H - -#include - - -#define MMC_EVENT_UARTBOARD_IN 0x01 -#define MMC_EVENT_UARTBOARD_OUT 0x02 - -#define MMC_EVENT_SDCARD_IN 0x04 -#define MMC_EVENT_SDCARD_OUT 0x08 - -#define MMC_EVENT_JTAG_IN 0x10 -#define MMC_EVENT_JTAG_OUT 0x20 - -#ifdef CONFIG_MMC_AML -extern int mmc_register_client(struct notifier_block *nb); -extern int mmc_unregister_client(struct notifier_block *nb); -extern int mmc_notifier_call_chain(unsigned long val, void *v); -#else /* !CONFIG_MMC_AML*/ -static inline int mmc_register_client(struct notifier_block *nb) -{ - return 0; -} - -static inline int mmc_unregister_client(struct notifier_block *nb) -{ - return 0; -}; - -static inline int mmc_notifier_call_chain(unsigned long val, void *v) -{ - return 0; -}; -#endif /* CONFIG_MMC_AML */ - -#endif