From b7ad4c67ed945524ab38bd61676e684eff84fc2a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 19 Mar 2024 10:37:21 +0100 Subject: backlight: omap1: Remove unused struct omap_backlight_config.set_power The callback set_power in struct omap_backlight_config is not implemented anywhere. Remove it from the structure and driver. Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg Reviewed-by: Daniel Thompson Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20240319093915.31778-3-tzimmermann@suse.de Signed-off-by: Lee Jones --- include/linux/platform_data/omap1_bl.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/omap1_bl.h b/include/linux/platform_data/omap1_bl.h index 5e8b17d77a5f..3d0bab31a0a9 100644 --- a/include/linux/platform_data/omap1_bl.h +++ b/include/linux/platform_data/omap1_bl.h @@ -6,7 +6,6 @@ struct omap_backlight_config { int default_intensity; - int (*set_power)(struct device *dev, int state); }; #endif -- cgit v1.2.3 From 67bb37c05a6b56e0e1f804706145a52f655af3f1 Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Wed, 27 Mar 2024 09:43:36 +0100 Subject: spi: spi-omap2-mcspi.c: revert "Toggle CS after each word" Commit 5cbc7ca987fb ("spi: spi-omap2-mcspi.c: Toggle CS after each word") introduced the toggling of CS after each word for the omap2-mcspi controller. The implementation is not respectful of the actual spi_message content, so the CS can be raised after each word even if the transfer structure asks to keep the CS active for the whole operation. As it is not used anyway in the current Linux tree, it can be safely removed. Signed-off-by: Louis Chauvet Link: https://msgid.link/r/20240327-spi-omap2-mcspi-multi-mode-v3-1-c4ac329dd5a2@bootlin.com Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 15 --------------- include/linux/platform_data/spi-omap2-mcspi.h | 3 --- 2 files changed, 18 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index ddf1c684bcc7..601acec37eca 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1175,13 +1175,6 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr, t->bits_per_word == spi->bits_per_word) par_override = 0; } - if (cd && cd->cs_per_word) { - chconf = mcspi->ctx.modulctrl; - chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE; - mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, chconf); - mcspi->ctx.modulctrl = - mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL); - } chconf = mcspi_cached_chconf0(spi); chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK; @@ -1240,14 +1233,6 @@ out: status = omap2_mcspi_setup_transfer(spi, NULL); } - if (cd && cd->cs_per_word) { - chconf = mcspi->ctx.modulctrl; - chconf |= OMAP2_MCSPI_MODULCTRL_SINGLE; - mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, chconf); - mcspi->ctx.modulctrl = - mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL); - } - omap2_mcspi_set_enable(spi, 0); if (spi_get_csgpiod(spi, 0)) diff --git a/include/linux/platform_data/spi-omap2-mcspi.h b/include/linux/platform_data/spi-omap2-mcspi.h index 3b400b1919a9..9e3c15b4ac91 100644 --- a/include/linux/platform_data/spi-omap2-mcspi.h +++ b/include/linux/platform_data/spi-omap2-mcspi.h @@ -16,9 +16,6 @@ struct omap2_mcspi_platform_config { struct omap2_mcspi_device_config { unsigned turbo_mode:1; - - /* toggle chip select after every word */ - unsigned cs_per_word:1; }; #endif -- cgit v1.2.3 From f81d13df1aa8b02fa8c6ac4b396dcda92fdfdac0 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Thu, 4 Apr 2024 13:16:44 +1300 Subject: platform/x86: asus-wmi: add support for 2024 ROG Mini-LED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support the 2024 mini-led backlight and adjust the related functions to select the relevant dev-id. Also add `available_mini_led_mode` to the platform sysfs since the available mini-led levels can be different. Reviewed-by: Ilpo Järvinen signed-off-by: Luke D. Jones Link: https://lore.kernel.org/r/20240404001652.86207-2-luke@ljones.dev Signed-off-by: Hans de Goede --- Documentation/ABI/testing/sysfs-platform-asus-wmi | 8 ++ drivers/platform/x86/asus-wmi.c | 96 ++++++++++++++++++++--- include/linux/platform_data/x86/asus-wmi.h | 1 + 3 files changed, 95 insertions(+), 10 deletions(-) (limited to 'include/linux/platform_data') diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi index 8a7e25bde085..ef1ac1a20a71 100644 --- a/Documentation/ABI/testing/sysfs-platform-asus-wmi +++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi @@ -126,6 +126,14 @@ Description: Change the mini-LED mode: * 0 - Single-zone, * 1 - Multi-zone + * 2 - Multi-zone strong (available on newer generation mini-led) + +What: /sys/devices/platform//available_mini_led_mode +Date: Apr 2024 +KernelVersion: 6.10 +Contact: "Luke Jones" +Description: + List the available mini-led modes. What: /sys/devices/platform//ppt_pl1_spl Date: Jun 2023 diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index df4c103459da..e8fbd7f9d343 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -126,6 +126,17 @@ module_param(fnlock_default, bool, 0444); #define ASUS_SCREENPAD_BRIGHT_MAX 255 #define ASUS_SCREENPAD_BRIGHT_DEFAULT 60 +#define ASUS_MINI_LED_MODE_MASK 0x03 +/* Standard modes for devices with only on/off */ +#define ASUS_MINI_LED_OFF 0x00 +#define ASUS_MINI_LED_ON 0x01 +/* New mode on some devices, define here to clarify remapping later */ +#define ASUS_MINI_LED_STRONG_MODE 0x02 +/* New modes for devices with 3 mini-led mode types */ +#define ASUS_MINI_LED_2024_WEAK 0x00 +#define ASUS_MINI_LED_2024_STRONG 0x01 +#define ASUS_MINI_LED_2024_OFF 0x02 + /* Controls the power state of the USB0 hub on ROG Ally which input is on */ #define ASUS_USB0_PWR_EC0_CSEE "\\_SB.PCI0.SBRG.EC0.CSEE" /* 300ms so far seems to produce a reliable result on AC and battery */ @@ -288,7 +299,7 @@ struct asus_wmi { bool battery_rsoc_available; bool panel_overdrive_available; - bool mini_led_mode_available; + u32 mini_led_dev_id; struct hotplug_slot hotplug_slot; struct mutex hotplug_lock; @@ -2108,13 +2119,33 @@ static ssize_t mini_led_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct asus_wmi *asus = dev_get_drvdata(dev); - int result; + u32 value; + int err; - result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_MINI_LED_MODE); - if (result < 0) - return result; + err = asus_wmi_get_devstate(asus, asus->mini_led_dev_id, &value); + if (err < 0) + return err; + value = value & ASUS_MINI_LED_MODE_MASK; - return sysfs_emit(buf, "%d\n", result); + /* + * Remap the mode values to match previous generation mini-led. The last gen + * WMI 0 == off, while on this version WMI 2 ==off (flipped). + */ + if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) { + switch (value) { + case ASUS_MINI_LED_2024_WEAK: + value = ASUS_MINI_LED_ON; + break; + case ASUS_MINI_LED_2024_STRONG: + value = ASUS_MINI_LED_STRONG_MODE; + break; + case ASUS_MINI_LED_2024_OFF: + value = ASUS_MINI_LED_OFF; + break; + } + } + + return sysfs_emit(buf, "%d\n", value); } static ssize_t mini_led_mode_store(struct device *dev, @@ -2130,11 +2161,32 @@ static ssize_t mini_led_mode_store(struct device *dev, if (result) return result; - if (mode > 1) + if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE && + mode > ASUS_MINI_LED_ON) + return -EINVAL; + if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2 && + mode > ASUS_MINI_LED_STRONG_MODE) return -EINVAL; - err = asus_wmi_set_devstate(ASUS_WMI_DEVID_MINI_LED_MODE, mode, &result); + /* + * Remap the mode values so expected behaviour is the same as the last + * generation of mini-LED with 0 == off, 1 == on. + */ + if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) { + switch (mode) { + case ASUS_MINI_LED_OFF: + mode = ASUS_MINI_LED_2024_OFF; + break; + case ASUS_MINI_LED_ON: + mode = ASUS_MINI_LED_2024_WEAK; + break; + case ASUS_MINI_LED_STRONG_MODE: + mode = ASUS_MINI_LED_2024_STRONG; + break; + } + } + err = asus_wmi_set_devstate(asus->mini_led_dev_id, mode, &result); if (err) { pr_warn("Failed to set mini-LED: %d\n", err); return err; @@ -2151,6 +2203,23 @@ static ssize_t mini_led_mode_store(struct device *dev, } static DEVICE_ATTR_RW(mini_led_mode); +static ssize_t available_mini_led_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct asus_wmi *asus = dev_get_drvdata(dev); + + switch (asus->mini_led_dev_id) { + case ASUS_WMI_DEVID_MINI_LED_MODE: + return sysfs_emit(buf, "0 1\n"); + case ASUS_WMI_DEVID_MINI_LED_MODE2: + return sysfs_emit(buf, "0 1 2\n"); + } + + return sysfs_emit(buf, "0\n"); +} + +static DEVICE_ATTR_RO(available_mini_led_mode); + /* Quirks *********************************************************************/ static void asus_wmi_set_xusb2pr(struct asus_wmi *asus) @@ -4139,6 +4208,7 @@ static struct attribute *platform_attributes[] = { &dev_attr_nv_temp_target.attr, &dev_attr_panel_od.attr, &dev_attr_mini_led_mode.attr, + &dev_attr_available_mini_led_mode.attr, NULL }; @@ -4191,7 +4261,9 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, else if (attr == &dev_attr_panel_od.attr) ok = asus->panel_overdrive_available; else if (attr == &dev_attr_mini_led_mode.attr) - ok = asus->mini_led_mode_available; + ok = asus->mini_led_dev_id != 0; + else if (attr == &dev_attr_available_mini_led_mode.attr) + ok = asus->mini_led_dev_id != 0; if (devid != -1) ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); @@ -4444,10 +4516,14 @@ static int asus_wmi_add(struct platform_device *pdev) asus->nv_dyn_boost_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_DYN_BOOST); asus->nv_temp_tgt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_THERM_TARGET); asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD); - asus->mini_led_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE); asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) && dmi_match(DMI_BOARD_NAME, "RC71L"); + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE)) + asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE; + else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE2)) + asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2; + err = fan_boost_mode_check_present(asus); if (err) goto fail_fan_boost_mode; diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index ab1c7deff118..9cadce10ad9a 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -71,6 +71,7 @@ #define ASUS_WMI_DEVID_LID_FLIP 0x00060062 #define ASUS_WMI_DEVID_LID_FLIP_ROG 0x00060077 #define ASUS_WMI_DEVID_MINI_LED_MODE 0x0005001E +#define ASUS_WMI_DEVID_MINI_LED_MODE2 0x0005002E /* Storage */ #define ASUS_WMI_DEVID_CARDREADER 0x00080013 -- cgit v1.2.3 From eb3bac90549a226df204a57eac45bbe5d6b4a0cf Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Thu, 4 Apr 2024 13:16:45 +1300 Subject: platform/x86: asus-wmi: add support for Vivobook GPU MUX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the Vivobook dgpu MUX available on the ASUS Viviobook and some of the other ranges (Zen). This MUX functions exactly the same as the existing ROG MUX support so the existing functionality now detects which MUX is available and uses that for control. Reviewed-by: Ilpo Järvinen Signed-off-by: Luke D. Jones Link: https://lore.kernel.org/r/20240404001652.86207-3-luke@ljones.dev Signed-off-by: Hans de Goede --- drivers/platform/x86/asus-wmi.c | 22 +++++++++++++--------- include/linux/platform_data/x86/asus-wmi.h | 1 + 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index e8fbd7f9d343..51e4df081046 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -270,7 +270,7 @@ struct asus_wmi { bool egpu_enable_available; bool egpu_connect_available; bool dgpu_disable_available; - bool gpu_mux_mode_available; + u32 gpu_mux_dev; /* Tunables provided by ASUS for gaming laptops */ bool ppt_pl2_sppt_available; @@ -693,8 +693,8 @@ static ssize_t dgpu_disable_store(struct device *dev, if (disable > 1) return -EINVAL; - if (asus->gpu_mux_mode_available) { - result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPU_MUX); + if (asus->gpu_mux_dev) { + result = asus_wmi_get_devstate_simple(asus, asus->gpu_mux_dev); if (result < 0) /* An error here may signal greater failure of GPU handling */ return result; @@ -759,8 +759,8 @@ static ssize_t egpu_enable_store(struct device *dev, return err; } - if (asus->gpu_mux_mode_available) { - result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPU_MUX); + if (asus->gpu_mux_dev) { + result = asus_wmi_get_devstate_simple(asus, asus->gpu_mux_dev); if (result < 0) { /* An error here may signal greater failure of GPU handling */ pr_warn("Failed to get gpu mux status: %d\n", result); @@ -813,7 +813,7 @@ static ssize_t gpu_mux_mode_show(struct device *dev, struct asus_wmi *asus = dev_get_drvdata(dev); int result; - result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPU_MUX); + result = asus_wmi_get_devstate_simple(asus, asus->gpu_mux_dev); if (result < 0) return result; @@ -859,7 +859,7 @@ static ssize_t gpu_mux_mode_store(struct device *dev, } } - err = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_MUX, optimus, &result); + err = asus_wmi_set_devstate(asus->gpu_mux_dev, optimus, &result); if (err) { dev_err(dev, "Failed to set GPU MUX mode: %d\n", err); return err; @@ -4239,7 +4239,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, else if (attr == &dev_attr_dgpu_disable.attr) ok = asus->dgpu_disable_available; else if (attr == &dev_attr_gpu_mux_mode.attr) - ok = asus->gpu_mux_mode_available; + ok = asus->gpu_mux_dev != 0; else if (attr == &dev_attr_fan_boost_mode.attr) ok = asus->fan_boost_mode_available; else if (attr == &dev_attr_throttle_thermal_policy.attr) @@ -4505,7 +4505,6 @@ static int asus_wmi_add(struct platform_device *pdev) asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); asus->egpu_connect_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); - asus->gpu_mux_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX); asus->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE); asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); asus->ppt_pl2_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL2_SPPT); @@ -4524,6 +4523,11 @@ static int asus_wmi_add(struct platform_device *pdev) else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE2)) asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2; + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX)) + asus->gpu_mux_dev = ASUS_WMI_DEVID_GPU_MUX; + else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX_VIVO)) + asus->gpu_mux_dev = ASUS_WMI_DEVID_GPU_MUX_VIVO; + err = fan_boost_mode_check_present(asus); if (err) goto fail_fan_boost_mode; diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 9cadce10ad9a..b48b024dd844 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -128,6 +128,7 @@ /* gpu mux switch, 0 = dGPU, 1 = Optimus */ #define ASUS_WMI_DEVID_GPU_MUX 0x00090016 +#define ASUS_WMI_DEVID_GPU_MUX_VIVO 0x00090026 /* TUF laptop RGB modes/colours */ #define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056 -- cgit v1.2.3 From ae834a549ec1d4cf372ffba1af1c14148807af55 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Thu, 4 Apr 2024 13:16:46 +1300 Subject: platform/x86: asus-wmi: add support variant of TUF RGB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for a second TUF RGB wmi call that some versions of the TUF laptop come with. Also adjusts existing support to select whichever is available. Reviewed-by: Ilpo Järvinen Signed-off-by: Luke D. Jones Link: https://lore.kernel.org/r/20240404001652.86207-4-luke@ljones.dev Signed-off-by: Hans de Goede --- drivers/platform/x86/asus-wmi.c | 13 +++++++++---- include/linux/platform_data/x86/asus-wmi.h | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 51e4df081046..113a80ae0efe 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -281,7 +281,7 @@ struct asus_wmi { bool nv_dyn_boost_available; bool nv_temp_tgt_available; - bool kbd_rgb_mode_available; + u32 kbd_rgb_dev; bool kbd_rgb_state_available; bool throttle_thermal_policy_available; @@ -881,6 +881,7 @@ static ssize_t kbd_rgb_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct asus_wmi *asus = dev_get_drvdata(dev); u32 cmd, mode, r, g, b, speed; int err; @@ -917,7 +918,7 @@ static ssize_t kbd_rgb_mode_store(struct device *dev, speed = 0xeb; } - err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS, ASUS_WMI_DEVID_TUF_RGB_MODE, + err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS, asus->kbd_rgb_dev, cmd | (mode << 8) | (r << 16) | (g << 24), b | (speed << 8), NULL); if (err) return err; @@ -1560,7 +1561,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) { int rv = 0, num_rgb_groups = 0, led_val; - if (asus->kbd_rgb_mode_available) + if (asus->kbd_rgb_dev) kbd_rgb_mode_groups[num_rgb_groups++] = &kbd_rgb_mode_group; if (asus->kbd_rgb_state_available) kbd_rgb_mode_groups[num_rgb_groups++] = &kbd_rgb_state_group; @@ -4505,7 +4506,6 @@ static int asus_wmi_add(struct platform_device *pdev) asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); asus->egpu_connect_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); - asus->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE); asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); asus->ppt_pl2_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL2_SPPT); asus->ppt_pl1_spl_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL1_SPL); @@ -4528,6 +4528,11 @@ static int asus_wmi_add(struct platform_device *pdev) else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX_VIVO)) asus->gpu_mux_dev = ASUS_WMI_DEVID_GPU_MUX_VIVO; + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE)) + asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE; + else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE2)) + asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE2; + err = fan_boost_mode_check_present(asus); if (err) goto fail_fan_boost_mode; diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index b48b024dd844..3e9a01467c67 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -132,6 +132,7 @@ /* TUF laptop RGB modes/colours */ #define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056 +#define ASUS_WMI_DEVID_TUF_RGB_MODE2 0x0010005A /* TUF laptop RGB power/state */ #define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057 -- cgit v1.2.3 From e0ae0ecce4869f841ea7cb20fca1b2c865c13339 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Thu, 4 Apr 2024 13:16:47 +1300 Subject: platform/x86: asus-wmi: support toggling POST sound MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for toggling the BIOS POST sound on some ASUS laptops. Reviewed-by: Ilpo Järvinen Signed-off-by: Luke D. Jones Link: https://lore.kernel.org/r/20240404001652.86207-5-luke@ljones.dev Signed-off-by: Hans de Goede --- Documentation/ABI/testing/sysfs-platform-asus-wmi | 9 ++++ drivers/platform/x86/asus-wmi.c | 51 +++++++++++++++++++++++ include/linux/platform_data/x86/asus-wmi.h | 3 ++ 3 files changed, 63 insertions(+) (limited to 'include/linux/platform_data') diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi index ef1ac1a20a71..72933527d2e4 100644 --- a/Documentation/ABI/testing/sysfs-platform-asus-wmi +++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi @@ -194,3 +194,12 @@ Contact: "Luke Jones" Description: Set the target temperature limit of the Nvidia dGPU: * min=75, max=87 + +What: /sys/devices/platform//boot_sound +Date: Apr 2024 +KernelVersion: 6.10 +Contact: "Luke Jones" +Description: + Set if the BIOS POST sound is played on boot. + * 0 - False, + * 1 - True diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 113a80ae0efe..1dbe473294f7 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -2115,6 +2115,54 @@ static ssize_t panel_od_store(struct device *dev, } static DEVICE_ATTR_RW(panel_od); +/* Bootup sound ***************************************************************/ + +static ssize_t boot_sound_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct asus_wmi *asus = dev_get_drvdata(dev); + int result; + + result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BOOT_SOUND); + if (result < 0) + return result; + + return sysfs_emit(buf, "%d\n", result); +} + +static ssize_t boot_sound_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int result, err; + u32 snd; + + struct asus_wmi *asus = dev_get_drvdata(dev); + + result = kstrtou32(buf, 10, &snd); + if (result) + return result; + + if (snd > 1) + return -EINVAL; + + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BOOT_SOUND, snd, &result); + if (err) { + pr_warn("Failed to set boot sound: %d\n", err); + return err; + } + + if (result > 1) { + pr_warn("Failed to set panel boot sound (result): 0x%x\n", result); + return -EIO; + } + + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "boot_sound"); + + return count; +} +static DEVICE_ATTR_RW(boot_sound); + /* Mini-LED mode **************************************************************/ static ssize_t mini_led_mode_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -4207,6 +4255,7 @@ static struct attribute *platform_attributes[] = { &dev_attr_ppt_platform_sppt.attr, &dev_attr_nv_dynamic_boost.attr, &dev_attr_nv_temp_target.attr, + &dev_attr_boot_sound.attr, &dev_attr_panel_od.attr, &dev_attr_mini_led_mode.attr, &dev_attr_available_mini_led_mode.attr, @@ -4259,6 +4308,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, ok = asus->nv_dyn_boost_available; else if (attr == &dev_attr_nv_temp_target.attr) ok = asus->nv_temp_tgt_available; + else if (attr == &dev_attr_boot_sound.attr) + devid = ASUS_WMI_DEVID_BOOT_SOUND; else if (attr == &dev_attr_panel_od.attr) ok = asus->panel_overdrive_available; else if (attr == &dev_attr_mini_led_mode.attr) diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 3e9a01467c67..3eb5cd6773ad 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -137,6 +137,9 @@ /* TUF laptop RGB power/state */ #define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057 +/* Bootup sound control */ +#define ASUS_WMI_DEVID_BOOT_SOUND 0x00130022 + /* DSTS masks */ #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002 -- cgit v1.2.3 From 904fb8f843a99ae7473d184412b6c7bd46a51593 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:03 +0200 Subject: ASoC: ti: davinci-i2s: Remove the unused clk_input_pin attribute The clk_input_pin attribute of davinci_mcbsp_dev struct is not set since commit 257ade78b601 ("ASoC: davinci-i2s: Convert to use edma-pcm"). Remove the attribute. Keep the behaviour of the MCBSP_CLKR case as MCBSP_CLKR == 0. I can't test the BC_FP format so I added back the initial comment that was removed by commit ec6375533748 ("ASoC: DaVinci: Added selection of clk input pin for McBSP"). This was the last dependency to linux/platform_data/davinci_asp.h so it is not included anymore. Remove the enum mcbsp_clk_input_pin from davinci_asp.h as it is not used anywhere else. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-4-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- include/linux/platform_data/davinci_asp.h | 15 --------------- sound/soc/ti/davinci-i2s.c | 24 ++++-------------------- 2 files changed, 4 insertions(+), 35 deletions(-) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index c8645b2ed3c0..b9c8520b4bd3 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -25,16 +25,6 @@ struct davinci_mcasp_pdata { unsigned sram_size_capture; struct gen_pool *sram_pool; - /* - * If McBSP peripheral gets the clock from an external pin, - * there are three chooses, that are MCBSP_CLKX, MCBSP_CLKR - * and MCBSP_CLKS. - * Depending on different hardware connections it is possible - * to use this setting to change the behaviour of McBSP - * driver. - */ - int clk_input_pin; - /* * This flag works when both clock and FS are outputs for the cpu * and makes clock more accurate (FS is not symmetrical and the @@ -91,11 +81,6 @@ enum { MCASP_VERSION_OMAP, /* OMAP4/5 */ }; -enum mcbsp_clk_input_pin { - MCBSP_CLKR = 0, /* as in DM365 */ - MCBSP_CLKS, -}; - #define INACTIVE_MODE 0 #define TX_MODE 1 #define RX_MODE 2 diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 07c8b2259208..5c906641640e 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -159,7 +158,6 @@ struct davinci_mcbsp_dev { unsigned int fmt; int clk_div; - int clk_input_pin; bool i2s_accurate_sck; }; @@ -239,26 +237,12 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, DAVINCI_MCBSP_PCR_CLKRM; break; case SND_SOC_DAIFMT_BC_FP: - pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM; /* - * Selection of the clock input pin that is the - * input for the Sample Rate Generator. - * McBSP FSR and FSX are driven by the Sample Rate - * Generator. + * McBSP CLKR pin is the input for the Sample Rate Generator. + * McBSP FSR and FSX are driven by the Sample Rate Generator. */ - switch (dev->clk_input_pin) { - case MCBSP_CLKS: - pcr |= DAVINCI_MCBSP_PCR_CLKXM | - DAVINCI_MCBSP_PCR_CLKRM; - break; - case MCBSP_CLKR: - pcr |= DAVINCI_MCBSP_PCR_SCLKME; - break; - default: - dev_err(dev->dev, "bad clk_input_pin\n"); - return -EINVAL; - } - + pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM; + pcr |= DAVINCI_MCBSP_PCR_SCLKME; break; case SND_SOC_DAIFMT_BC_FC: /* codec is master */ -- cgit v1.2.3 From 1019fa4839c97c4efff9c26af4d74a184921d8da Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Wed, 10 Apr 2024 09:48:03 -0500 Subject: uio: pruss: Remove this driver This UIO driver was used to control the PRU processors found on various TI SoCs. It was created before the Remoteproc framework, but now with that we have a standard way to program and manage the PRU processors. The proper PRU Remoteproc driver should be used instead of this driver. This driver only supported the original class of PRUSS (OMAP-L1xx / AM17xx / AM18xx / TMS320C674x / DA8xx) but when these platforms were switched to use Device Tree the support for DT was not added to this driver and so it is now unused/unusable. Support for these platforms can be added to the proper PRU Remoteproc driver if ever needed. Remove this driver. Signed-off-by: Andrew Davis Link: https://lore.kernel.org/r/20240410144803.126831-1-afd@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/uio/Kconfig | 18 --- drivers/uio/Makefile | 1 - drivers/uio/uio_pruss.c | 255 -------------------------------- include/linux/platform_data/uio_pruss.h | 18 --- 4 files changed, 292 deletions(-) delete mode 100644 drivers/uio/uio_pruss.c delete mode 100644 include/linux/platform_data/uio_pruss.h (limited to 'include/linux/platform_data') diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 2e16c5338e5b..b060dcd7c635 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -125,24 +125,6 @@ config UIO_FSL_ELBC_GPCM_NETX5152 Information about this hardware can be found at: http://www.hilscher.com/netx -config UIO_PRUSS - tristate "Texas Instruments PRUSS driver" - select GENERIC_ALLOCATOR - depends on HAS_IOMEM && HAS_DMA - help - PRUSS driver for OMAPL138/DA850/AM18XX devices - PRUSS driver requires user space components, examples and user space - driver is available from below SVN repo - you may use anonymous login - - https://gforge.ti.com/gf/project/pru_sw/ - - More info on API is available at below wiki - - http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader - - To compile this driver as a module, choose M here: the module - will be called uio_pruss. - config UIO_MF624 tristate "Humusoft MF624 DAQ PCI card driver" depends on PCI diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index f2f416a14228..1c5f3b5a95cf 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_UIO_AEC) += uio_aec.o obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o obj-$(CONFIG_UIO_NETX) += uio_netx.o -obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o obj-$(CONFIG_UIO_MF624) += uio_mf624.o obj-$(CONFIG_UIO_FSL_ELBC_GPCM) += uio_fsl_elbc_gpcm.o obj-$(CONFIG_UIO_HV_GENERIC) += uio_hv_generic.o diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c deleted file mode 100644 index f67881cba645..000000000000 --- a/drivers/uio/uio_pruss.c +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Programmable Real-Time Unit Sub System (PRUSS) UIO driver (uio_pruss) - * - * This driver exports PRUSS host event out interrupts and PRUSS, L3 RAM, - * and DDR RAM to user space for applications interacting with PRUSS firmware - * - * Copyright (C) 2010-11 Texas Instruments Incorporated - http://www.ti.com/ - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pruss_uio" -#define DRV_VERSION "1.0" - -static int sram_pool_sz = SZ_16K; -module_param(sram_pool_sz, int, 0); -MODULE_PARM_DESC(sram_pool_sz, "sram pool size to allocate "); - -static int extram_pool_sz = SZ_256K; -module_param(extram_pool_sz, int, 0); -MODULE_PARM_DESC(extram_pool_sz, "external ram pool size to allocate"); - -/* - * Host event IRQ numbers from PRUSS - PRUSS can generate up to 8 interrupt - * events to AINTC of ARM host processor - which can be used for IPC b/w PRUSS - * firmware and user space application, async notification from PRU firmware - * to user space application - * 3 PRU_EVTOUT0 - * 4 PRU_EVTOUT1 - * 5 PRU_EVTOUT2 - * 6 PRU_EVTOUT3 - * 7 PRU_EVTOUT4 - * 8 PRU_EVTOUT5 - * 9 PRU_EVTOUT6 - * 10 PRU_EVTOUT7 -*/ -#define MAX_PRUSS_EVT 8 - -#define PINTC_HIDISR 0x0038 -#define PINTC_HIPIR 0x0900 -#define HIPIR_NOPEND 0x80000000 -#define PINTC_HIER 0x1500 - -struct uio_pruss_dev { - struct uio_info *info; - struct clk *pruss_clk; - dma_addr_t sram_paddr; - dma_addr_t ddr_paddr; - void __iomem *prussio_vaddr; - unsigned long sram_vaddr; - void *ddr_vaddr; - unsigned int hostirq_start; - unsigned int pintc_base; - struct gen_pool *sram_pool; -}; - -static irqreturn_t pruss_handler(int irq, struct uio_info *info) -{ - struct uio_pruss_dev *gdev = info->priv; - int intr_bit = (irq - gdev->hostirq_start + 2); - int val, intr_mask = (1 << intr_bit); - void __iomem *base = gdev->prussio_vaddr + gdev->pintc_base; - void __iomem *intren_reg = base + PINTC_HIER; - void __iomem *intrdis_reg = base + PINTC_HIDISR; - void __iomem *intrstat_reg = base + PINTC_HIPIR + (intr_bit << 2); - - val = ioread32(intren_reg); - /* Is interrupt enabled and active ? */ - if (!(val & intr_mask) && (ioread32(intrstat_reg) & HIPIR_NOPEND)) - return IRQ_NONE; - /* Disable interrupt */ - iowrite32(intr_bit, intrdis_reg); - return IRQ_HANDLED; -} - -static void pruss_cleanup(struct device *dev, struct uio_pruss_dev *gdev) -{ - int cnt; - struct uio_info *p = gdev->info; - - for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) { - uio_unregister_device(p); - } - iounmap(gdev->prussio_vaddr); - if (gdev->ddr_vaddr) { - dma_free_coherent(dev, extram_pool_sz, gdev->ddr_vaddr, - gdev->ddr_paddr); - } - if (gdev->sram_vaddr) - gen_pool_free(gdev->sram_pool, - gdev->sram_vaddr, - sram_pool_sz); - clk_disable(gdev->pruss_clk); -} - -static int pruss_probe(struct platform_device *pdev) -{ - struct uio_info *p; - struct uio_pruss_dev *gdev; - struct resource *regs_prussio; - struct device *dev = &pdev->dev; - int ret, cnt, i, len; - struct uio_pruss_pdata *pdata = dev_get_platdata(dev); - - gdev = devm_kzalloc(dev, sizeof(struct uio_pruss_dev), GFP_KERNEL); - if (!gdev) - return -ENOMEM; - - gdev->info = devm_kcalloc(dev, MAX_PRUSS_EVT, sizeof(*p), GFP_KERNEL); - if (!gdev->info) - return -ENOMEM; - - /* Power on PRU in case its not done as part of boot-loader */ - gdev->pruss_clk = devm_clk_get(dev, "pruss"); - if (IS_ERR(gdev->pruss_clk)) { - dev_err(dev, "Failed to get clock\n"); - return PTR_ERR(gdev->pruss_clk); - } - - ret = clk_enable(gdev->pruss_clk); - if (ret) { - dev_err(dev, "Failed to enable clock\n"); - return ret; - } - - regs_prussio = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs_prussio) { - dev_err(dev, "No PRUSS I/O resource specified\n"); - ret = -EIO; - goto err_clk_disable; - } - - if (!regs_prussio->start) { - dev_err(dev, "Invalid memory resource\n"); - ret = -EIO; - goto err_clk_disable; - } - - if (pdata->sram_pool) { - gdev->sram_pool = pdata->sram_pool; - gdev->sram_vaddr = - (unsigned long)gen_pool_dma_alloc(gdev->sram_pool, - sram_pool_sz, &gdev->sram_paddr); - if (!gdev->sram_vaddr) { - dev_err(dev, "Could not allocate SRAM pool\n"); - ret = -ENOMEM; - goto err_clk_disable; - } - } - - gdev->ddr_vaddr = dma_alloc_coherent(dev, extram_pool_sz, - &(gdev->ddr_paddr), GFP_KERNEL | GFP_DMA); - if (!gdev->ddr_vaddr) { - dev_err(dev, "Could not allocate external memory\n"); - ret = -ENOMEM; - goto err_free_sram; - } - - len = resource_size(regs_prussio); - gdev->prussio_vaddr = ioremap(regs_prussio->start, len); - if (!gdev->prussio_vaddr) { - dev_err(dev, "Can't remap PRUSS I/O address range\n"); - ret = -ENOMEM; - goto err_free_ddr_vaddr; - } - - ret = platform_get_irq(pdev, 0); - if (ret < 0) - goto err_unmap; - - gdev->hostirq_start = ret; - gdev->pintc_base = pdata->pintc_base; - - for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) { - p->mem[0].addr = regs_prussio->start; - p->mem[0].size = resource_size(regs_prussio); - p->mem[0].memtype = UIO_MEM_PHYS; - - p->mem[1].addr = gdev->sram_paddr; - p->mem[1].size = sram_pool_sz; - p->mem[1].memtype = UIO_MEM_PHYS; - - p->mem[2].addr = (uintptr_t) gdev->ddr_vaddr; - p->mem[2].dma_addr = gdev->ddr_paddr; - p->mem[2].size = extram_pool_sz; - p->mem[2].memtype = UIO_MEM_DMA_COHERENT; - p->mem[2].dma_device = dev; - - p->name = devm_kasprintf(dev, GFP_KERNEL, "pruss_evt%d", cnt); - p->version = DRV_VERSION; - - /* Register PRUSS IRQ lines */ - p->irq = gdev->hostirq_start + cnt; - p->handler = pruss_handler; - p->priv = gdev; - - ret = uio_register_device(dev, p); - if (ret < 0) - goto err_unloop; - } - - platform_set_drvdata(pdev, gdev); - return 0; - -err_unloop: - for (i = 0, p = gdev->info; i < cnt; i++, p++) { - uio_unregister_device(p); - } -err_unmap: - iounmap(gdev->prussio_vaddr); -err_free_ddr_vaddr: - dma_free_coherent(dev, extram_pool_sz, gdev->ddr_vaddr, - gdev->ddr_paddr); -err_free_sram: - if (pdata->sram_pool) - gen_pool_free(gdev->sram_pool, gdev->sram_vaddr, sram_pool_sz); -err_clk_disable: - clk_disable(gdev->pruss_clk); - - return ret; -} - -static int pruss_remove(struct platform_device *dev) -{ - struct uio_pruss_dev *gdev = platform_get_drvdata(dev); - - pruss_cleanup(&dev->dev, gdev); - return 0; -} - -static struct platform_driver pruss_driver = { - .probe = pruss_probe, - .remove = pruss_remove, - .driver = { - .name = DRV_NAME, - }, -}; - -module_platform_driver(pruss_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(DRV_VERSION); -MODULE_AUTHOR("Amit Chatterjee "); -MODULE_AUTHOR("Pratheesh Gangadhar "); diff --git a/include/linux/platform_data/uio_pruss.h b/include/linux/platform_data/uio_pruss.h deleted file mode 100644 index f76fa393b802..000000000000 --- a/include/linux/platform_data/uio_pruss.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * include/linux/platform_data/uio_pruss.h - * - * Platform data for uio_pruss driver - * - * Copyright (C) 2010-11 Texas Instruments Incorporated - https://www.ti.com/ - */ - -#ifndef _UIO_PRUSS_H_ -#define _UIO_PRUSS_H_ - -/* To configure the PRUSS INTC base offset for UIO driver */ -struct uio_pruss_pdata { - u32 pintc_base; - struct gen_pool *sram_pool; -}; -#endif /* _UIO_PRUSS_H_ */ -- cgit v1.2.3 From 4bcc2e91b9e77644ee04b290bfd2c1410d7c402e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 11 Apr 2024 07:44:30 +0300 Subject: bus: ti-sysc: Drop legacy idle quirk handling There are no more users that need the legacy idle quirk so let's drop the legacy idle quirk handling. This simplifies the PM code to just sysc_pm_ops with unified handling for all the interconnect targets. Reviewed-by: Dhruva Gole Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 109 +--------------------------------- include/linux/platform_data/ti-sysc.h | 1 - 2 files changed, 2 insertions(+), 108 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 467702da0e82..8767e04d6c89 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1469,8 +1469,7 @@ static int __maybe_unused sysc_noirq_suspend(struct device *dev) ddata = dev_get_drvdata(dev); - if (ddata->cfg.quirks & - (SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE)) + if (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE) return 0; if (!ddata->enabled) @@ -1488,8 +1487,7 @@ static int __maybe_unused sysc_noirq_resume(struct device *dev) ddata = dev_get_drvdata(dev); - if (ddata->cfg.quirks & - (SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE)) + if (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE) return 0; if (ddata->cfg.quirks & SYSC_QUIRK_REINIT_ON_RESUME) { @@ -2457,89 +2455,6 @@ static int __maybe_unused sysc_child_runtime_resume(struct device *dev) return pm_generic_runtime_resume(dev); } -#ifdef CONFIG_PM_SLEEP -static int sysc_child_suspend_noirq(struct device *dev) -{ - struct sysc *ddata; - int error; - - ddata = sysc_child_to_parent(dev); - - dev_dbg(ddata->dev, "%s %s\n", __func__, - ddata->name ? ddata->name : ""); - - error = pm_generic_suspend_noirq(dev); - if (error) { - dev_err(dev, "%s error at %i: %i\n", - __func__, __LINE__, error); - - return error; - } - - if (!pm_runtime_status_suspended(dev)) { - error = pm_generic_runtime_suspend(dev); - if (error) { - dev_dbg(dev, "%s busy at %i: %i\n", - __func__, __LINE__, error); - - return 0; - } - - error = sysc_runtime_suspend(ddata->dev); - if (error) { - dev_err(dev, "%s error at %i: %i\n", - __func__, __LINE__, error); - - return error; - } - - ddata->child_needs_resume = true; - } - - return 0; -} - -static int sysc_child_resume_noirq(struct device *dev) -{ - struct sysc *ddata; - int error; - - ddata = sysc_child_to_parent(dev); - - dev_dbg(ddata->dev, "%s %s\n", __func__, - ddata->name ? ddata->name : ""); - - if (ddata->child_needs_resume) { - ddata->child_needs_resume = false; - - error = sysc_runtime_resume(ddata->dev); - if (error) - dev_err(ddata->dev, - "%s runtime resume error: %i\n", - __func__, error); - - error = pm_generic_runtime_resume(dev); - if (error) - dev_err(ddata->dev, - "%s generic runtime resume: %i\n", - __func__, error); - } - - return pm_generic_resume_noirq(dev); -} -#endif - -static struct dev_pm_domain sysc_child_pm_domain = { - .ops = { - SET_RUNTIME_PM_OPS(sysc_child_runtime_suspend, - sysc_child_runtime_resume, - NULL) - USE_PLATFORM_PM_SLEEP_OPS - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sysc_child_suspend_noirq, - sysc_child_resume_noirq) - } -}; - /* Caller needs to take list_lock if ever used outside of cpu_pm */ static void sysc_reinit_modules(struct sysc_soc_info *soc) { @@ -2610,25 +2525,6 @@ out_unlock: mutex_unlock(&sysc_soc->list_lock); } -/** - * sysc_legacy_idle_quirk - handle children in omap_device compatible way - * @ddata: device driver data - * @child: child device driver - * - * Allow idle for child devices as done with _od_runtime_suspend(). - * Otherwise many child devices will not idle because of the permanent - * parent usecount set in pm_runtime_irq_safe(). - * - * Note that the long term solution is to just modify the child device - * drivers to not set pm_runtime_irq_safe() and then this can be just - * dropped. - */ -static void sysc_legacy_idle_quirk(struct sysc *ddata, struct device *child) -{ - if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) - dev_pm_domain_set(child, &sysc_child_pm_domain); -} - static int sysc_notifier_call(struct notifier_block *nb, unsigned long event, void *device) { @@ -2645,7 +2541,6 @@ static int sysc_notifier_call(struct notifier_block *nb, error = sysc_child_add_clocks(ddata, dev); if (error) return error; - sysc_legacy_idle_quirk(ddata, dev); break; default: break; diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index eb556f988d57..d8f15770a522 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -71,7 +71,6 @@ struct sysc_regbits { #define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12) #define SYSC_QUIRK_SWSUP_SIDLE BIT(11) #define SYSC_QUIRK_EXT_OPT_CLOCK BIT(10) -#define SYSC_QUIRK_LEGACY_IDLE BIT(9) #define SYSC_QUIRK_RESET_STATUS BIT(8) #define SYSC_QUIRK_NO_IDLE BIT(7) #define SYSC_QUIRK_NO_IDLE_ON_INIT BIT(6) -- cgit v1.2.3 From 073e58bf6b1a689da2ffcfc7fc515005f8794018 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 15 Apr 2024 22:48:42 +0200 Subject: i2c: mux: gpio: remove support for class-based device instantiation i801 as only user of gpio i2c mux removed support for class-based device instantiation on muxed busses. Class-based device instantiation is a legacy mechanism and shouldn't be used in new code, therefore remove support also here. Signed-off-by: Heiner Kallweit Signed-off-by: Andi Shyti --- drivers/i2c/muxes/i2c-mux-gpio.c | 3 +-- include/linux/platform_data/i2c-mux-gpio.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 6b979a0a6ab8..0fbb33a3d518 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -206,9 +206,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) for (i = 0; i < mux->data.n_values; i++) { u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0; - unsigned int class = mux->data.classes ? mux->data.classes[i] : 0; - ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class); + ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], 0); if (ret) goto add_adapter_failed; } diff --git a/include/linux/platform_data/i2c-mux-gpio.h b/include/linux/platform_data/i2c-mux-gpio.h index 5e4c2c272a73..816a4cd3ccb5 100644 --- a/include/linux/platform_data/i2c-mux-gpio.h +++ b/include/linux/platform_data/i2c-mux-gpio.h @@ -18,7 +18,6 @@ * @values: Array of bitmasks of GPIO settings (low/high) for each * position * @n_values: Number of multiplexer positions (busses to instantiate) - * @classes: Optional I2C auto-detection classes * @idle: Bitmask to write to MUX when idle or GPIO_I2CMUX_NO_IDLE if not used */ struct i2c_mux_gpio_platform_data { @@ -26,7 +25,6 @@ struct i2c_mux_gpio_platform_data { int base_nr; const unsigned *values; int n_values; - const unsigned *classes; unsigned idle; }; -- cgit v1.2.3 From a14a569a9918a0c7e340257a17dbc088bb27db72 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Wed, 29 May 2024 08:27:11 +0200 Subject: platform/chrome: cros_ec_proto: Introduce cros_ec_cmd_readmem() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To read from the EC memory different mechanism are possible. ECs connected via LPC expose their memory via a ->cmd_readmem operation. Other protocols require the usage of EC_CMD_READ_MEMMAP, which on the other hand is not implemented by LPC ECs. Provide a helper that automatically selects the correct mechanism. Signed-off-by: Thomas Weißschuh Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20240529-cros_ec-hwmon-v4-1-5cdf0c5db50a@weissschuh.net Signed-off-by: Tzung-Bi Shih --- drivers/platform/chrome/cros_ec_proto.c | 27 +++++++++++++++++++++++++++ include/linux/platform_data/cros_ec_proto.h | 2 ++ 2 files changed, 29 insertions(+) (limited to 'include/linux/platform_data') diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index dcfc18fe1cdf..2ad1b8221ec0 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -1033,3 +1033,30 @@ error: return ret; } EXPORT_SYMBOL_GPL(cros_ec_cmd); + +/** + * cros_ec_cmd_readmem - Read from EC memory. + * + * @ec_dev: EC device + * @offset: Is within EC_LPC_ADDR_MEMMAP region. + * @size: Number of bytes to read. + * @dest: EC command output data + * + * Return: >= 0 on success, negative error number on failure. + */ +int cros_ec_cmd_readmem(struct cros_ec_device *ec_dev, u8 offset, u8 size, void *dest) +{ + struct ec_params_read_memmap params = {}; + + if (!size) + return -EINVAL; + + if (ec_dev->cmd_readmem) + return ec_dev->cmd_readmem(ec_dev, offset, size, dest); + + params.offset = offset; + params.size = size; + return cros_ec_cmd(ec_dev, 0, EC_CMD_READ_MEMMAP, + ¶ms, sizeof(params), dest, size); +} +EXPORT_SYMBOL_GPL(cros_ec_cmd_readmem); diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index 8865e350c12a..1ddc52603f9a 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -261,6 +261,8 @@ int cros_ec_get_sensor_count(struct cros_ec_dev *ec); int cros_ec_cmd(struct cros_ec_device *ec_dev, unsigned int version, int command, const void *outdata, size_t outsize, void *indata, size_t insize); +int cros_ec_cmd_readmem(struct cros_ec_device *ec_dev, u8 offset, u8 size, void *dest); + /** * cros_ec_get_time_ns() - Return time in ns. * -- cgit v1.2.3 From ba098ed9829c5de4d65e5708d08d3508f2e70a7d Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Tue, 4 Jun 2024 10:01:48 -0700 Subject: platform/chrome: Add struct ec_response_get_next_event_v3 Add struct ec_response_get_next_event_v3 to upgrade EC_CMD_GET_NEXT_EVENT to version 3. Signed-off-by: Daisuke Nojiri Link: https://lore.kernel.org/r/20240604170552.2517189-1-dnojiri@chromium.org Signed-off-by: Tzung-Bi Shih --- include/linux/platform_data/cros_ec_commands.h | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index ecc47d5fe239..ec598057d1da 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -3463,6 +3463,34 @@ union __ec_align_offset1 ec_response_get_next_data_v1 { }; BUILD_ASSERT(sizeof(union ec_response_get_next_data_v1) == 16); +union __ec_align_offset1 ec_response_get_next_data_v3 { + uint8_t key_matrix[18]; + + /* Unaligned */ + uint32_t host_event; + uint64_t host_event64; + + struct __ec_todo_unpacked { + /* For aligning the fifo_info */ + uint8_t reserved[3]; + struct ec_response_motion_sense_fifo_info info; + } sensor_fifo; + + uint32_t buttons; + + uint32_t switches; + + uint32_t fp_events; + + uint32_t sysrq; + + /* CEC events from enum mkbp_cec_event */ + uint32_t cec_events; + + uint8_t cec_message[16]; +}; +BUILD_ASSERT(sizeof(union ec_response_get_next_data_v3) == 18); + struct ec_response_get_next_event { uint8_t event_type; /* Followed by event data if any */ @@ -3475,6 +3503,12 @@ struct ec_response_get_next_event_v1 { union ec_response_get_next_data_v1 data; } __ec_align1; +struct ec_response_get_next_event_v3 { + uint8_t event_type; + /* Followed by event data if any */ + union ec_response_get_next_data_v3 data; +} __ec_align1; + /* Bit indices for buttons and switches.*/ /* Buttons */ #define EC_MKBP_POWER_BUTTON 0 -- cgit v1.2.3 From 106d6739823369c734a8fc3b13634274eee4f60e Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Tue, 4 Jun 2024 16:08:25 -0700 Subject: platform/chrome: cros_ec_proto: Upgrade get_next_event to v3 Upgrade EC_CMD_GET_NEXT_EVENT to version 3. The max supported version will be v3. So, we speak v3 even if the EC says it supports v4+. Signed-off-by: Daisuke Nojiri Link: https://lore.kernel.org/r/20240604230837.2878737-1-dnojiri@chromium.org [tzungbi: uint32_t -> u32 per suggested by checkpatch.pl] Signed-off-by: Tzung-Bi Shih --- drivers/platform/chrome/cros_ec_proto.c | 27 ++++++++++++++++++--------- include/linux/platform_data/cros_ec_proto.h | 2 +- 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 2ad1b8221ec0..fe68be66ee98 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -684,7 +684,7 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer_status); static int get_next_event_xfer(struct cros_ec_device *ec_dev, struct cros_ec_command *msg, - struct ec_response_get_next_event_v1 *event, + struct ec_response_get_next_event_v3 *event, int version, uint32_t size) { int ret; @@ -707,11 +707,12 @@ static int get_next_event(struct cros_ec_device *ec_dev) { struct { struct cros_ec_command msg; - struct ec_response_get_next_event_v1 event; + struct ec_response_get_next_event_v3 event; } __packed buf; struct cros_ec_command *msg = &buf.msg; - struct ec_response_get_next_event_v1 *event = &buf.event; - const int cmd_version = ec_dev->mkbp_event_supported - 1; + struct ec_response_get_next_event_v3 *event = &buf.event; + int cmd_version = ec_dev->mkbp_event_supported - 1; + u32 size; memset(msg, 0, sizeof(*msg)); if (ec_dev->suspended) { @@ -719,12 +720,20 @@ static int get_next_event(struct cros_ec_device *ec_dev) return -EHOSTDOWN; } - if (cmd_version == 0) - return get_next_event_xfer(ec_dev, msg, event, 0, - sizeof(struct ec_response_get_next_event)); + if (cmd_version == 0) { + size = sizeof(struct ec_response_get_next_event); + } else if (cmd_version < 3) { + size = sizeof(struct ec_response_get_next_event_v1); + } else { + /* + * The max version we support is v3. So, we speak v3 even if the + * EC says it supports v4+. + */ + cmd_version = 3; + size = sizeof(struct ec_response_get_next_event_v3); + } - return get_next_event_xfer(ec_dev, msg, event, cmd_version, - sizeof(struct ec_response_get_next_event_v1)); + return get_next_event_xfer(ec_dev, msg, event, cmd_version, size); } static int get_keyboard_state_event(struct cros_ec_device *ec_dev) diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index 1ddc52603f9a..6e9225bdf903 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -185,7 +185,7 @@ struct cros_ec_device { bool host_sleep_v1; struct blocking_notifier_head event_notifier; - struct ec_response_get_next_event_v1 event_data; + struct ec_response_get_next_event_v3 event_data; int event_size; u32 host_event_wake_mask; u32 last_resume_result; -- cgit v1.2.3 From a31a0a3e90b442c1a414be24b062e27624a40a8e Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Tue, 28 May 2024 11:47:16 -0700 Subject: thermal: intel: intel_soc_dts_thermal: Switch to new Intel CPU model defines New CPU #defines encode vendor and family as well as model. Signed-off-by: Tony Luck Acked-by: Rafael J. Wysocki Signed-off-by: Rafael J. Wysocki --- drivers/thermal/intel/intel_soc_dts_thermal.c | 2 +- include/linux/platform_data/x86/soc.h | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/thermal/intel/intel_soc_dts_thermal.c b/drivers/thermal/intel/intel_soc_dts_thermal.c index 9c825c6e1f38..718c6326eaf4 100644 --- a/drivers/thermal/intel/intel_soc_dts_thermal.c +++ b/drivers/thermal/intel/intel_soc_dts_thermal.c @@ -36,7 +36,7 @@ static irqreturn_t soc_irq_thread_fn(int irq, void *dev_data) } static const struct x86_cpu_id soc_thermal_ids[] = { - X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, BYT_SOC_DTS_APIC_IRQ), + X86_MATCH_VFM(INTEL_ATOM_SILVERMONT, BYT_SOC_DTS_APIC_IRQ), {} }; MODULE_DEVICE_TABLE(x86cpu, soc_thermal_ids); diff --git a/include/linux/platform_data/x86/soc.h b/include/linux/platform_data/x86/soc.h index a5705189e2ac..f981907a5cb0 100644 --- a/include/linux/platform_data/x86/soc.h +++ b/include/linux/platform_data/x86/soc.h @@ -20,7 +20,7 @@ static inline bool soc_intel_is_##soc(void) \ { \ static const struct x86_cpu_id soc##_cpu_ids[] = { \ - X86_MATCH_INTEL_FAM6_MODEL(type, NULL), \ + X86_MATCH_VFM(type, NULL), \ {} \ }; \ const struct x86_cpu_id *id; \ @@ -31,11 +31,11 @@ static inline bool soc_intel_is_##soc(void) \ return false; \ } -SOC_INTEL_IS_CPU(byt, ATOM_SILVERMONT); -SOC_INTEL_IS_CPU(cht, ATOM_AIRMONT); -SOC_INTEL_IS_CPU(apl, ATOM_GOLDMONT); -SOC_INTEL_IS_CPU(glk, ATOM_GOLDMONT_PLUS); -SOC_INTEL_IS_CPU(cml, KABYLAKE_L); +SOC_INTEL_IS_CPU(byt, INTEL_ATOM_SILVERMONT); +SOC_INTEL_IS_CPU(cht, INTEL_ATOM_AIRMONT); +SOC_INTEL_IS_CPU(apl, INTEL_ATOM_GOLDMONT); +SOC_INTEL_IS_CPU(glk, INTEL_ATOM_GOLDMONT_PLUS); +SOC_INTEL_IS_CPU(cml, INTEL_KABYLAKE_L); #undef SOC_INTEL_IS_CPU -- cgit v1.2.3 From 5e5f2f92cccc29f356422d3cbc104f7f42430f22 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 14 Jun 2024 02:43:39 +0300 Subject: platform: arm64: add Lenovo Yoga C630 WOS EC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lenovo Yoga C630 WOS is a laptop using Snapdragon 850 SoC. Like many laptops it uses an embedded controller (EC) to perform various platform operations, including, but not limited, to Type-C port control or power supply handlng. Add the driver for the EC, that creates devices for UCSI and power supply devices. Reviewed-by: Bryan O'Donoghue Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240614-yoga-ec-driver-v7-2-9f0b9b40ae76@linaro.org [ij: added #include ] Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/arm64/Kconfig | 14 ++ drivers/platform/arm64/Makefile | 1 + drivers/platform/arm64/lenovo-yoga-c630.c | 291 +++++++++++++++++++++++++ include/linux/platform_data/lenovo-yoga-c630.h | 44 ++++ 4 files changed, 350 insertions(+) create mode 100644 drivers/platform/arm64/lenovo-yoga-c630.c create mode 100644 include/linux/platform_data/lenovo-yoga-c630.h (limited to 'include/linux/platform_data') diff --git a/drivers/platform/arm64/Kconfig b/drivers/platform/arm64/Kconfig index 8fdca0f8e909..8c103b3150d1 100644 --- a/drivers/platform/arm64/Kconfig +++ b/drivers/platform/arm64/Kconfig @@ -32,4 +32,18 @@ config EC_ACER_ASPIRE1 laptop where this information is not properly exposed via the standard ACPI devices. +config EC_LENOVO_YOGA_C630 + tristate "Lenovo Yoga C630 Embedded Controller driver" + depends on I2C + help + Driver for the Embedded Controller in the Qualcomm Snapdragon-based + Lenovo Yoga C630, which provides battery and power adapter + information. + + This driver provides battery and AC status support for the mentioned + laptop where this information is not properly exposed via the + standard ACPI devices. + + Say M or Y here to include this support. + endif # ARM64_PLATFORM_DEVICES diff --git a/drivers/platform/arm64/Makefile b/drivers/platform/arm64/Makefile index 4fcc9855579b..b2ae9114fdd8 100644 --- a/drivers/platform/arm64/Makefile +++ b/drivers/platform/arm64/Makefile @@ -6,3 +6,4 @@ # obj-$(CONFIG_EC_ACER_ASPIRE1) += acer-aspire1-ec.o +obj-$(CONFIG_EC_LENOVO_YOGA_C630) += lenovo-yoga-c630.o diff --git a/drivers/platform/arm64/lenovo-yoga-c630.c b/drivers/platform/arm64/lenovo-yoga-c630.c new file mode 100644 index 000000000000..1f05c9a6a89d --- /dev/null +++ b/drivers/platform/arm64/lenovo-yoga-c630.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024, Linaro Ltd + * Authors: + * Bjorn Andersson + * Dmitry Baryshkov + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LENOVO_EC_RESPONSE_REG 0x01 +#define LENOVO_EC_REQUEST_REG 0x02 + +#define LENOVO_EC_UCSI_WRITE 0x20 +#define LENOVO_EC_UCSI_READ 0x21 + +#define LENOVO_EC_READ_REG 0xb0 +#define LENOVO_EC_REQUEST_NEXT_EVENT 0x84 + +#define LENOVO_EC_UCSI_VERSION 0x20 + +struct yoga_c630_ec { + struct i2c_client *client; + struct mutex lock; + struct blocking_notifier_head notifier_list; +}; + +static int yoga_c630_ec_request(struct yoga_c630_ec *ec, u8 *req, size_t req_len, + u8 *resp, size_t resp_len) +{ + int ret; + + lockdep_assert_held(&ec->lock); + + ret = i2c_smbus_write_i2c_block_data(ec->client, LENOVO_EC_REQUEST_REG, + req_len, req); + if (ret < 0) + return ret; + + return i2c_smbus_read_i2c_block_data(ec->client, LENOVO_EC_RESPONSE_REG, + resp_len, resp); +} + +int yoga_c630_ec_read8(struct yoga_c630_ec *ec, u8 addr) +{ + u8 req[2] = { LENOVO_EC_READ_REG, }; + int ret; + u8 val; + + guard(mutex)(&ec->lock); + + req[1] = addr; + ret = yoga_c630_ec_request(ec, req, sizeof(req), &val, 1); + if (ret < 0) + return ret; + + return val; +} +EXPORT_SYMBOL_GPL(yoga_c630_ec_read8); + +int yoga_c630_ec_read16(struct yoga_c630_ec *ec, u8 addr) +{ + u8 req[2] = { LENOVO_EC_READ_REG, }; + int ret; + u8 msb; + u8 lsb; + + /* don't overflow the address */ + if (addr == 0xff) + return -EINVAL; + + guard(mutex)(&ec->lock); + + req[1] = addr; + ret = yoga_c630_ec_request(ec, req, sizeof(req), &lsb, 1); + if (ret < 0) + return ret; + + req[1] = addr + 1; + ret = yoga_c630_ec_request(ec, req, sizeof(req), &msb, 1); + if (ret < 0) + return ret; + + return msb << 8 | lsb; +} +EXPORT_SYMBOL_GPL(yoga_c630_ec_read16); + +u16 yoga_c630_ec_ucsi_get_version(struct yoga_c630_ec *ec) +{ + u8 req[3] = { 0xb3, 0xf2, }; + int ret; + u8 msb; + u8 lsb; + + guard(mutex)(&ec->lock); + + req[2] = LENOVO_EC_UCSI_VERSION; + ret = yoga_c630_ec_request(ec, req, sizeof(req), &lsb, 1); + if (ret < 0) + return ret; + + req[2] = LENOVO_EC_UCSI_VERSION + 1; + ret = yoga_c630_ec_request(ec, req, sizeof(req), &msb, 1); + if (ret < 0) + return ret; + + return msb << 8 | lsb; +} +EXPORT_SYMBOL_GPL(yoga_c630_ec_ucsi_get_version); + +int yoga_c630_ec_ucsi_write(struct yoga_c630_ec *ec, + const u8 req[YOGA_C630_UCSI_WRITE_SIZE]) +{ + int ret; + + mutex_lock(&ec->lock); + ret = i2c_smbus_write_i2c_block_data(ec->client, LENOVO_EC_UCSI_WRITE, + YOGA_C630_UCSI_WRITE_SIZE, req); + mutex_unlock(&ec->lock); + + return ret < 0 ? ret : 0; +} +EXPORT_SYMBOL_GPL(yoga_c630_ec_ucsi_write); + +int yoga_c630_ec_ucsi_read(struct yoga_c630_ec *ec, + u8 resp[YOGA_C630_UCSI_READ_SIZE]) +{ + int ret; + + mutex_lock(&ec->lock); + ret = i2c_smbus_read_i2c_block_data(ec->client, LENOVO_EC_UCSI_READ, + YOGA_C630_UCSI_READ_SIZE, resp); + mutex_unlock(&ec->lock); + + return ret < 0 ? ret : 0; +} +EXPORT_SYMBOL_GPL(yoga_c630_ec_ucsi_read); + +static irqreturn_t yoga_c630_ec_thread_intr(int irq, void *data) +{ + u8 req[] = { LENOVO_EC_REQUEST_NEXT_EVENT }; + struct yoga_c630_ec *ec = data; + u8 event; + int ret; + + mutex_lock(&ec->lock); + ret = yoga_c630_ec_request(ec, req, sizeof(req), &event, 1); + mutex_unlock(&ec->lock); + if (ret < 0) + return IRQ_HANDLED; + + blocking_notifier_call_chain(&ec->notifier_list, event, ec); + + return IRQ_HANDLED; +} + +/** + * yoga_c630_ec_register_notify - Register a notifier callback for EC events. + * @ec: Yoga C630 EC + * @nb: Notifier block pointer to register + * + * Return: 0 on success or negative error code. + */ +int yoga_c630_ec_register_notify(struct yoga_c630_ec *ec, struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&ec->notifier_list, nb); +} +EXPORT_SYMBOL_GPL(yoga_c630_ec_register_notify); + +/** + * yoga_c630_ec_unregister_notify - Unregister notifier callback for EC events. + * @ec: Yoga C630 EC + * @nb: Notifier block pointer to unregister + * + * Unregister a notifier callback that was previously registered with + * yoga_c630_ec_register_notify(). + */ +void yoga_c630_ec_unregister_notify(struct yoga_c630_ec *ec, struct notifier_block *nb) +{ + blocking_notifier_chain_unregister(&ec->notifier_list, nb); +} +EXPORT_SYMBOL_GPL(yoga_c630_ec_unregister_notify); + +static void yoga_c630_aux_release(struct device *dev) +{ + struct auxiliary_device *adev = to_auxiliary_dev(dev); + + kfree(adev); +} + +static void yoga_c630_aux_remove(void *data) +{ + struct auxiliary_device *adev = data; + + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); +} + +static int yoga_c630_aux_init(struct device *parent, const char *name, + struct yoga_c630_ec *ec) +{ + struct auxiliary_device *adev; + int ret; + + adev = kzalloc(sizeof(*adev), GFP_KERNEL); + if (!adev) + return -ENOMEM; + + adev->name = name; + adev->id = 0; + adev->dev.parent = parent; + adev->dev.release = yoga_c630_aux_release; + adev->dev.platform_data = ec; + + ret = auxiliary_device_init(adev); + if (ret) { + kfree(adev); + return ret; + } + + ret = auxiliary_device_add(adev); + if (ret) { + auxiliary_device_uninit(adev); + return ret; + } + + return devm_add_action_or_reset(parent, yoga_c630_aux_remove, adev); +} + +static int yoga_c630_ec_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct yoga_c630_ec *ec; + int ret; + + ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL); + if (!ec) + return -ENOMEM; + + mutex_init(&ec->lock); + ec->client = client; + BLOCKING_INIT_NOTIFIER_HEAD(&ec->notifier_list); + + ret = devm_request_threaded_irq(dev, client->irq, + NULL, yoga_c630_ec_thread_intr, + IRQF_ONESHOT, "yoga_c630_ec", ec); + if (ret < 0) + return dev_err_probe(dev, ret, "unable to request irq\n"); + + ret = yoga_c630_aux_init(dev, YOGA_C630_DEV_PSY, ec); + if (ret) + return ret; + + return yoga_c630_aux_init(dev, YOGA_C630_DEV_UCSI, ec); +} + + +static const struct of_device_id yoga_c630_ec_of_match[] = { + { .compatible = "lenovo,yoga-c630-ec" }, + {} +}; +MODULE_DEVICE_TABLE(of, yoga_c630_ec_of_match); + +static const struct i2c_device_id yoga_c630_ec_i2c_id_table[] = { + { "yoga-c630-ec", }, + {} +}; +MODULE_DEVICE_TABLE(i2c, yoga_c630_ec_i2c_id_table); + +static struct i2c_driver yoga_c630_ec_i2c_driver = { + .driver = { + .name = "yoga-c630-ec", + .of_match_table = yoga_c630_ec_of_match + }, + .probe = yoga_c630_ec_probe, + .id_table = yoga_c630_ec_i2c_id_table, +}; +module_i2c_driver(yoga_c630_ec_i2c_driver); + +MODULE_DESCRIPTION("Lenovo Yoga C630 Embedded Controller"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/platform_data/lenovo-yoga-c630.h b/include/linux/platform_data/lenovo-yoga-c630.h new file mode 100644 index 000000000000..5d1f9fb33cfc --- /dev/null +++ b/include/linux/platform_data/lenovo-yoga-c630.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024, Linaro Ltd + * Authors: + * Bjorn Andersson + * Dmitry Baryshkov + */ + +#ifndef _LENOVO_YOGA_C630_DATA_H +#define _LENOVO_YOGA_C630_DATA_H + +struct yoga_c630_ec; +struct notifier_block; + +#define YOGA_C630_MOD_NAME "lenovo_yoga_c630" + +#define YOGA_C630_DEV_UCSI "ucsi" +#define YOGA_C630_DEV_PSY "psy" + +int yoga_c630_ec_read8(struct yoga_c630_ec *ec, u8 addr); +int yoga_c630_ec_read16(struct yoga_c630_ec *ec, u8 addr); + +int yoga_c630_ec_register_notify(struct yoga_c630_ec *ec, struct notifier_block *nb); +void yoga_c630_ec_unregister_notify(struct yoga_c630_ec *ec, struct notifier_block *nb); + +#define YOGA_C630_UCSI_WRITE_SIZE 8 +#define YOGA_C630_UCSI_CCI_SIZE 4 +#define YOGA_C630_UCSI_DATA_SIZE 16 +#define YOGA_C630_UCSI_READ_SIZE (YOGA_C630_UCSI_CCI_SIZE + YOGA_C630_UCSI_DATA_SIZE) + +u16 yoga_c630_ec_ucsi_get_version(struct yoga_c630_ec *ec); +int yoga_c630_ec_ucsi_write(struct yoga_c630_ec *ec, + const u8 req[YOGA_C630_UCSI_WRITE_SIZE]); +int yoga_c630_ec_ucsi_read(struct yoga_c630_ec *ec, + u8 resp[YOGA_C630_UCSI_READ_SIZE]); + +#define LENOVO_EC_EVENT_USB 0x20 +#define LENOVO_EC_EVENT_UCSI 0x21 +#define LENOVO_EC_EVENT_HPD 0x22 +#define LENOVO_EC_EVENT_BAT_STATUS 0x24 +#define LENOVO_EC_EVENT_BAT_INFO 0x25 +#define LENOVO_EC_EVENT_BAT_ADPT_STATUS 0x37 + +#endif -- cgit v1.2.3 From c05cb5bdf413a2a5051701a397082380758e37ec Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Sun, 30 Jun 2024 22:54:09 +0200 Subject: platform/chrome: Update binary interface for EC-based charge control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The charge-control command v2/v3 is more featureful than v1, it additionally supports charge thresholds. The definitions were imported from ChromeOS EC commit 32870d602317 ("squirtle: modify motionsense rotation matrix") Signed-off-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20240630-cros_ec-charge-control-v5-2-8f649d018c52@weissschuh.net Signed-off-by: Tzung-Bi Shih --- include/linux/platform_data/cros_ec_commands.h | 49 ++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index ec598057d1da..e574b790be6f 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -3843,16 +3843,61 @@ struct ec_params_i2c_write { * discharge the battery. */ #define EC_CMD_CHARGE_CONTROL 0x0096 -#define EC_VER_CHARGE_CONTROL 1 +#define EC_VER_CHARGE_CONTROL 3 enum ec_charge_control_mode { CHARGE_CONTROL_NORMAL = 0, CHARGE_CONTROL_IDLE, CHARGE_CONTROL_DISCHARGE, + /* Add no more entry below. */ + CHARGE_CONTROL_COUNT, +}; + +#define EC_CHARGE_MODE_TEXT \ + { \ + [CHARGE_CONTROL_NORMAL] = "NORMAL", \ + [CHARGE_CONTROL_IDLE] = "IDLE", \ + [CHARGE_CONTROL_DISCHARGE] = "DISCHARGE", \ + } + +enum ec_charge_control_cmd { + EC_CHARGE_CONTROL_CMD_SET = 0, + EC_CHARGE_CONTROL_CMD_GET, +}; + +enum ec_charge_control_flag { + EC_CHARGE_CONTROL_FLAG_NO_IDLE = BIT(0), }; struct ec_params_charge_control { - uint32_t mode; /* enum charge_control_mode */ + uint32_t mode; /* enum charge_control_mode */ + + /* Below are the fields added in V2. */ + uint8_t cmd; /* enum ec_charge_control_cmd. */ + uint8_t flags; /* enum ec_charge_control_flag (v3+) */ + /* + * Lower and upper thresholds for battery sustainer. This struct isn't + * named to avoid tainting foreign projects' name spaces. + * + * If charge mode is explicitly set (e.g. DISCHARGE), battery sustainer + * will be disabled. To disable battery sustainer, set mode=NORMAL, + * lower=-1, upper=-1. + */ + struct { + int8_t lower; /* Display SoC in percentage. */ + int8_t upper; /* Display SoC in percentage. */ + } sustain_soc; +} __ec_align4; + +/* Added in v2 */ +struct ec_response_charge_control { + uint32_t mode; /* enum charge_control_mode */ + struct { /* Battery sustainer thresholds */ + int8_t lower; + int8_t upper; + } sustain_soc; + uint8_t flags; /* enum ec_charge_control_flag (v3+) */ + uint8_t reserved; } __ec_align4; /*****************************************************************************/ -- cgit v1.2.3 From 69a13742b7c64ed89894caf7091539e164b3e97c Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Sun, 30 Jun 2024 22:54:10 +0200 Subject: platform/chrome: cros_ec_proto: Introduce cros_ec_get_cmd_versions() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Retrieving the supported versions of a command is a fairly common operation. Provide a helper for it. If the command is not supported at all the EC returns -EINVAL/EC_RES_INVALID_PARAMS. This error is translated into an empty version mask as that is easier to handle for callers and they don't need to know about the error details. Signed-off-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20240630-cros_ec-charge-control-v5-3-8f649d018c52@weissschuh.net Signed-off-by: Tzung-Bi Shih --- drivers/platform/chrome/cros_ec_proto.c | 35 +++++++++++++++++++++++++++++ include/linux/platform_data/cros_ec_proto.h | 2 ++ 2 files changed, 37 insertions(+) (limited to 'include/linux/platform_data') diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index fe68be66ee98..f776fd42244f 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -1069,3 +1070,37 @@ int cros_ec_cmd_readmem(struct cros_ec_device *ec_dev, u8 offset, u8 size, void ¶ms, sizeof(params), dest, size); } EXPORT_SYMBOL_GPL(cros_ec_cmd_readmem); + +/** + * cros_ec_get_cmd_versions - Get supported version mask. + * + * @ec_dev: EC device + * @cmd: Command to test + * + * Return: version mask on success, negative error number on failure. + */ +int cros_ec_get_cmd_versions(struct cros_ec_device *ec_dev, u16 cmd) +{ + struct ec_params_get_cmd_versions req_v0; + struct ec_params_get_cmd_versions_v1 req_v1; + struct ec_response_get_cmd_versions resp; + int ret; + + if (cmd <= U8_MAX) { + req_v0.cmd = cmd; + ret = cros_ec_cmd(ec_dev, 0, EC_CMD_GET_CMD_VERSIONS, + &req_v0, sizeof(req_v0), &resp, sizeof(resp)); + } else { + req_v1.cmd = cmd; + ret = cros_ec_cmd(ec_dev, 1, EC_CMD_GET_CMD_VERSIONS, + &req_v1, sizeof(req_v1), &resp, sizeof(resp)); + } + + if (ret == -EINVAL) + return 0; /* Command not implemented */ + else if (ret < 0) + return ret; + else + return resp.version_mask; +} +EXPORT_SYMBOL_GPL(cros_ec_get_cmd_versions); diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index 6e9225bdf903..b34ed0cc1f8d 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -263,6 +263,8 @@ int cros_ec_cmd(struct cros_ec_device *ec_dev, unsigned int version, int command int cros_ec_cmd_readmem(struct cros_ec_device *ec_dev, u8 offset, u8 size, void *dest); +int cros_ec_get_cmd_versions(struct cros_ec_device *ec_dev, u16 cmd); + /** * cros_ec_get_time_ns() - Return time in ns. * -- cgit v1.2.3 From 4bf1ea3fc914faef37d8c793b7144d4765ff4a00 Mon Sep 17 00:00:00 2001 From: Devin Bayer Date: Fri, 28 Jun 2024 10:46:03 +0200 Subject: platform/x86: asus-wmi: support the disable camera LED on F10 of Zenbook 2023 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a sysfs entry for the LED on F10 above the crossed out camera icon on 2023 Zenbooks. Signed-off-by: Devin Bayer Link: https://lore.kernel.org/r/20240628084603.217106-1-dev@doubly.so Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/asus-wmi.c | 35 ++++++++++++++++++++++++++++++ include/linux/platform_data/x86/asus-wmi.h | 4 ++++ 2 files changed, 39 insertions(+) (limited to 'include/linux/platform_data') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 3f9b6285c9a6..26c45fd093a0 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -238,6 +238,7 @@ struct asus_wmi { struct led_classdev lightbar_led; int lightbar_led_wk; struct led_classdev micmute_led; + struct led_classdev camera_led; struct workqueue_struct *led_workqueue; struct work_struct tpd_led_work; struct work_struct wlan_led_work; @@ -1642,6 +1643,27 @@ static int micmute_led_set(struct led_classdev *led_cdev, return err < 0 ? err : 0; } +static enum led_brightness camera_led_get(struct led_classdev *led_cdev) +{ + struct asus_wmi *asus; + u32 result; + + asus = container_of(led_cdev, struct asus_wmi, camera_led); + asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_CAMERA_LED, &result); + + return result & ASUS_WMI_DSTS_BRIGHTNESS_MASK; +} + +static int camera_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + int state = brightness != LED_OFF; + int err; + + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_CAMERA_LED, state, NULL); + return err < 0 ? err : 0; +} + static void asus_wmi_led_exit(struct asus_wmi *asus) { led_classdev_unregister(&asus->kbd_led); @@ -1649,6 +1671,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus) led_classdev_unregister(&asus->wlan_led); led_classdev_unregister(&asus->lightbar_led); led_classdev_unregister(&asus->micmute_led); + led_classdev_unregister(&asus->camera_led); if (asus->led_workqueue) destroy_workqueue(asus->led_workqueue); @@ -1740,6 +1763,18 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CAMERA_LED)) { + asus->camera_led.name = "asus::camera"; + asus->camera_led.max_brightness = 1; + asus->camera_led.brightness_get = camera_led_get; + asus->camera_led.brightness_set_blocking = camera_led_set; + + rv = led_classdev_register(&asus->platform_device->dev, + &asus->camera_led); + if (rv) + goto error; + } + error: if (rv) asus_wmi_led_exit(asus); diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 3eb5cd6773ad..0aeeae1c1943 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -51,6 +51,10 @@ #define ASUS_WMI_DEVID_LED6 0x00020016 #define ASUS_WMI_DEVID_MICMUTE_LED 0x00040017 +/* Disable Camera LED */ +#define ASUS_WMI_DEVID_CAMERA_LED_NEG 0x00060078 /* 0 = on (unused) */ +#define ASUS_WMI_DEVID_CAMERA_LED 0x00060079 /* 1 = on */ + /* Backlight and Brightness */ #define ASUS_WMI_DEVID_ALS_ENABLE 0x00050001 /* Ambient Light Sensor */ #define ASUS_WMI_DEVID_BACKLIGHT 0x00050011 -- cgit v1.2.3 From 70b46487b1558eb25ea6e533c905131b10596dc0 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 13 Feb 2024 23:02:25 +0100 Subject: mfd: tmio: Move header to platform_data All the MFD components are gone from the header meanwhile. Only the MMC relevant data is left which makes it a platform_data for the MMC controller. Move the header to the now fitting directory. Signed-off-by: Wolfram Sang Acked-by: Ulf Hansson # For MMC Acked-by: John Paul Adrian Glaubitz Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20240213220221.2380-14-wsa+renesas@sang-engineering.com Signed-off-by: Lee Jones --- MAINTAINERS | 2 +- arch/sh/boards/board-sh7757lcr.c | 2 +- arch/sh/boards/mach-ap325rxa/setup.c | 2 +- arch/sh/boards/mach-ecovec24/setup.c | 2 +- arch/sh/boards/mach-kfr2r09/setup.c | 2 +- arch/sh/boards/mach-migor/setup.c | 2 +- arch/sh/boards/mach-se/7724/setup.c | 2 +- drivers/mmc/host/renesas_sdhi_core.c | 2 +- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 2 +- drivers/mmc/host/renesas_sdhi_sys_dmac.c | 2 +- drivers/mmc/host/tmio_mmc_core.c | 2 +- drivers/mmc/host/uniphier-sd.c | 2 +- include/linux/mfd/tmio.h | 64 --------------------------- include/linux/platform_data/tmio.h | 64 +++++++++++++++++++++++++++ 14 files changed, 76 insertions(+), 76 deletions(-) delete mode 100644 include/linux/mfd/tmio.h create mode 100644 include/linux/platform_data/tmio.h (limited to 'include/linux/platform_data') diff --git a/MAINTAINERS b/MAINTAINERS index 17af347464d2..5d13fe1a9187 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22685,7 +22685,7 @@ L: linux-renesas-soc@vger.kernel.org S: Supported F: drivers/mmc/host/renesas_sdhi* F: drivers/mmc/host/tmio_mmc* -F: include/linux/mfd/tmio.h +F: include/linux/platform_data/tmio.h TMP513 HARDWARE MONITOR DRIVER M: Eric Tremblay diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c index 689ea14a6678..bca54e489e11 100644 --- a/arch/sh/boards/board-sh7757lcr.c +++ b/arch/sh/boards/board-sh7757lcr.c @@ -14,9 +14,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index 645cccf3da88..bb5004a8ac02 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -24,10 +24,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 30d117f9ad7e..6f13557eecd6 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -17,13 +17,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include #include diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 6b775eae85c0..70236859919d 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -22,10 +22,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 773ee767d0c4..1853e6319a66 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 787ddd3c627a..e500feb91053 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -21,9 +21,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 12f4faaaf4ee..d9503f9f6e96 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -22,13 +22,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include #include diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index e8c3fb0fb5c2..4a02ef7fde4d 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -11,12 +11,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #include diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c index c18581897f8a..68e31c37cce6 100644 --- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c @@ -11,12 +11,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #include diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 73b0bd692fe0..592506d83e2c 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -39,6 +38,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index 1404989e6151..bd231dbe90ba 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -9,11 +9,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h deleted file mode 100644 index 1cf418643da9..000000000000 --- a/include/linux/mfd/tmio.h +++ /dev/null @@ -1,64 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef MFD_TMIO_H -#define MFD_TMIO_H - -#include -#include - -/* TMIO MMC platform flags */ - -/* - * Some controllers can support a 2-byte block size when the bus width is - * configured in 4-bit mode. - */ -#define TMIO_MMC_BLKSZ_2BYTES BIT(1) - -/* Some controllers can support SDIO IRQ signalling */ -#define TMIO_MMC_SDIO_IRQ BIT(2) - -/* Some features are only available or tested on R-Car Gen2 or later */ -#define TMIO_MMC_MIN_RCAR2 BIT(3) - -/* - * Some controllers require waiting for the SD bus to become idle before - * writing to some registers. - */ -#define TMIO_MMC_HAS_IDLE_WAIT BIT(4) - -/* - * Use the busy timeout feature. Probably all TMIO versions support it. Yet, - * we don't have documentation for old variants, so we enable only known good - * variants with this flag. Can be removed once all variants are known good. - */ -#define TMIO_MMC_USE_BUSY_TIMEOUT BIT(5) - -/* Some controllers have CMD12 automatically issue/non-issue register */ -#define TMIO_MMC_HAVE_CMD12_CTRL BIT(7) - -/* Controller has some SDIO status bits which must be 1 */ -#define TMIO_MMC_SDIO_STATUS_SETBITS BIT(8) - -/* Some controllers have a 32-bit wide data port register */ -#define TMIO_MMC_32BIT_DATA_PORT BIT(9) - -/* Some controllers allows to set SDx actual clock */ -#define TMIO_MMC_CLK_ACTUAL BIT(10) - -/* Some controllers have a CBSY bit */ -#define TMIO_MMC_HAVE_CBSY BIT(11) - -struct tmio_mmc_data { - void *chan_priv_tx; - void *chan_priv_rx; - unsigned int hclk; - unsigned long capabilities; - unsigned long capabilities2; - unsigned long flags; - u32 ocr_mask; /* available voltages */ - dma_addr_t dma_rx_offset; - unsigned int max_blk_count; - unsigned short max_segs; - void (*set_pwr)(struct platform_device *host, int state); - void (*set_clk_div)(struct platform_device *host, int state); -}; -#endif diff --git a/include/linux/platform_data/tmio.h b/include/linux/platform_data/tmio.h new file mode 100644 index 000000000000..1cf418643da9 --- /dev/null +++ b/include/linux/platform_data/tmio.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef MFD_TMIO_H +#define MFD_TMIO_H + +#include +#include + +/* TMIO MMC platform flags */ + +/* + * Some controllers can support a 2-byte block size when the bus width is + * configured in 4-bit mode. + */ +#define TMIO_MMC_BLKSZ_2BYTES BIT(1) + +/* Some controllers can support SDIO IRQ signalling */ +#define TMIO_MMC_SDIO_IRQ BIT(2) + +/* Some features are only available or tested on R-Car Gen2 or later */ +#define TMIO_MMC_MIN_RCAR2 BIT(3) + +/* + * Some controllers require waiting for the SD bus to become idle before + * writing to some registers. + */ +#define TMIO_MMC_HAS_IDLE_WAIT BIT(4) + +/* + * Use the busy timeout feature. Probably all TMIO versions support it. Yet, + * we don't have documentation for old variants, so we enable only known good + * variants with this flag. Can be removed once all variants are known good. + */ +#define TMIO_MMC_USE_BUSY_TIMEOUT BIT(5) + +/* Some controllers have CMD12 automatically issue/non-issue register */ +#define TMIO_MMC_HAVE_CMD12_CTRL BIT(7) + +/* Controller has some SDIO status bits which must be 1 */ +#define TMIO_MMC_SDIO_STATUS_SETBITS BIT(8) + +/* Some controllers have a 32-bit wide data port register */ +#define TMIO_MMC_32BIT_DATA_PORT BIT(9) + +/* Some controllers allows to set SDx actual clock */ +#define TMIO_MMC_CLK_ACTUAL BIT(10) + +/* Some controllers have a CBSY bit */ +#define TMIO_MMC_HAVE_CBSY BIT(11) + +struct tmio_mmc_data { + void *chan_priv_tx; + void *chan_priv_rx; + unsigned int hclk; + unsigned long capabilities; + unsigned long capabilities2; + unsigned long flags; + u32 ocr_mask; /* available voltages */ + dma_addr_t dma_rx_offset; + unsigned int max_blk_count; + unsigned short max_segs; + void (*set_pwr)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); +}; +#endif -- cgit v1.2.3 From 444b89875fc0937ece181fa865c75c9d22649986 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 28 Jun 2024 11:08:48 -0700 Subject: ARM: spitz: Use software nodes to describe MMC GPIOs Convert Spitz to use software nodes for specifying GPIOs for the MMC. Signed-off-by: Dmitry Torokhov Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20240628180852.1738922-9-dmitry.torokhov@gmail.com Signed-off-by: Arnd Bergmann --- arch/arm/mach-pxa/devices.c | 36 ++++++++++++++++++-------------- arch/arm/mach-pxa/devices.h | 1 - arch/arm/mach-pxa/gumstix.c | 2 +- arch/arm/mach-pxa/spitz.c | 18 +++++++--------- include/linux/platform_data/mmc-pxamci.h | 4 +++- 5 files changed, 31 insertions(+), 30 deletions(-) (limited to 'include/linux/platform_data') diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index e2758c94fd77..d050a4c78f97 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -48,7 +48,7 @@ struct platform_device pxa_device_pmu = { .num_resources = 1, }; -static struct resource pxamci_resources[] = { +static const struct resource pxamci_resources[] = { [0] = { .start = 0x41100000, .end = 0x41100fff, @@ -61,22 +61,26 @@ static struct resource pxamci_resources[] = { }, }; -static u64 pxamci_dmamask = 0xffffffffUL; - -struct platform_device pxa_device_mci = { - .name = "pxa2xx-mci", - .id = 0, - .dev = { - .dma_mask = &pxamci_dmamask, - .coherent_dma_mask = 0xffffffff, - }, - .num_resources = ARRAY_SIZE(pxamci_resources), - .resource = pxamci_resources, -}; - -void __init pxa_set_mci_info(struct pxamci_platform_data *info) +void __init pxa_set_mci_info(const struct pxamci_platform_data *info, + const struct property_entry *props) { - pxa_register_device(&pxa_device_mci, info); + const struct platform_device_info mci_info = { + .name = "pxa2xx-mci", + .id = 0, + .res = pxamci_resources, + .num_res = ARRAY_SIZE(pxamci_resources), + .data = info, + .size_data = sizeof(*info), + .dma_mask = 0xffffffffUL, + .properties = props, + }; + struct platform_device *mci_dev; + int err; + + mci_dev = platform_device_register_full(&mci_info); + err = PTR_ERR_OR_ZERO(mci_dev); + if (err) + pr_err("Unable to create mci device: %d\n", err); } static struct pxa2xx_udc_mach_info pxa_udc_info = { diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h index b7c0e138ef61..72c556ff67db 100644 --- a/arch/arm/mach-pxa/devices.h +++ b/arch/arm/mach-pxa/devices.h @@ -4,7 +4,6 @@ struct mmp_dma_platdata; extern struct platform_device pxa_device_pmu; -extern struct platform_device pxa_device_mci; extern struct platform_device pxa3xx_device_mci2; extern struct platform_device pxa3xx_device_mci3; extern struct platform_device pxa25x_device_udc; diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c index b9eddc691097..efa6faa62a2c 100644 --- a/arch/arm/mach-pxa/gumstix.c +++ b/arch/arm/mach-pxa/gumstix.c @@ -90,7 +90,7 @@ static struct pxamci_platform_data gumstix_mci_platform_data = { static void __init gumstix_mmc_init(void) { - pxa_set_mci_info(&gumstix_mci_platform_data); + pxa_set_mci_info(&gumstix_mci_platform_data, NULL); } #else static void __init gumstix_mmc_init(void) diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index c79510185ce3..4720a40587f1 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -651,21 +651,17 @@ static struct pxamci_platform_data spitz_mci_platform_data = { .setpower = spitz_mci_setpower, }; -static struct gpiod_lookup_table spitz_mci_gpio_table = { - .dev_id = "pxa2xx-mci.0", - .table = { - GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_nSD_DETECT, - "cd", GPIO_ACTIVE_LOW), - GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_nSD_WP, - "wp", GPIO_ACTIVE_LOW), - { }, - }, +static const struct property_entry spitz_mci_props[] __initconst = { + PROPERTY_ENTRY_GPIO("cd-gpios", &pxa2xx_gpiochip_node, + SPITZ_GPIO_nSD_DETECT, GPIO_ACTIVE_LOW), + PROPERTY_ENTRY_GPIO("wp-gpios", &pxa2xx_gpiochip_node, + SPITZ_GPIO_nSD_WP, GPIO_ACTIVE_LOW), + { } }; static void __init spitz_mmc_init(void) { - gpiod_add_lookup_table(&spitz_mci_gpio_table); - pxa_set_mci_info(&spitz_mci_platform_data); + pxa_set_mci_info(&spitz_mci_platform_data, spitz_mci_props); } #else static inline void spitz_mmc_init(void) {} diff --git a/include/linux/platform_data/mmc-pxamci.h b/include/linux/platform_data/mmc-pxamci.h index 7e44e84e7150..652f323b5ecc 100644 --- a/include/linux/platform_data/mmc-pxamci.h +++ b/include/linux/platform_data/mmc-pxamci.h @@ -7,6 +7,7 @@ struct device; struct mmc_host; +struct property_entry; struct pxamci_platform_data { unsigned int ocr_mask; /* available voltages */ @@ -18,7 +19,8 @@ struct pxamci_platform_data { bool gpio_card_ro_invert; /* gpio ro is inverted */ }; -extern void pxa_set_mci_info(struct pxamci_platform_data *info); +extern void pxa_set_mci_info(const struct pxamci_platform_data *info, + const struct property_entry *props); extern void pxa3xx_set_mci2_info(struct pxamci_platform_data *info); extern void pxa3xx_set_mci3_info(struct pxamci_platform_data *info); -- cgit v1.2.3 From e8858fc07eb8386b9b6436d3e86eeb4b81e4f660 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 13 Jul 2024 23:00:27 -0700 Subject: Input: msc5000_ts - remove the driver MCS-5000 belongs to the 1st generation of Melfas chips, manufactured in 2000-2007. The driver relies on custom platform data (no DT support) and there never were any users of this driver in the mainline kernel. The commit adding the driver mentioned that the driver was tested on S3C6410 NCP board (with Samsung S3C6410 SoC) but the touchscreen device was never added to the board file. This board was removed in v6.3 in commit 743c8fbb90ca ("ARM: s3c: remove most s3c64xx board support"). Remove the driver since there are no users. Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240714060029.1528662-1-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 12 -- drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/mcs5000_ts.c | 288 --------------------------------- include/linux/platform_data/mcs.h | 4 - 4 files changed, 305 deletions(-) delete mode 100644 drivers/input/touchscreen/mcs5000_ts.c (limited to 'include/linux/platform_data') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index c821fe3ee794..0df90c3d743b 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -626,18 +626,6 @@ config TOUCHSCREEN_MAX11801 To compile this driver as a module, choose M here: the module will be called max11801_ts. -config TOUCHSCREEN_MCS5000 - tristate "MELFAS MCS-5000 touchscreen" - depends on I2C - help - Say Y here if you have the MELFAS MCS-5000 touchscreen controller - chip in your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called mcs5000_ts. - config TOUCHSCREEN_MMS114 tristate "MELFAS MMS114 touchscreen" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index a81cb5aa21a5..04dc8039341b 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -63,7 +63,6 @@ obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o obj-$(CONFIG_TOUCHSCREEN_MXS_LRADC) += mxs-lradc-ts.o obj-$(CONFIG_TOUCHSCREEN_MX25) += fsl-imx25-tcq.o obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o -obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o obj-$(CONFIG_TOUCHSCREEN_MELFAS_MIP4) += melfas_mip4.o obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o obj-$(CONFIG_TOUCHSCREEN_MMS114) += mms114.o diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c deleted file mode 100644 index 5aff8dcda0dc..000000000000 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ /dev/null @@ -1,288 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * mcs5000_ts.c - Touchscreen driver for MELFAS MCS-5000 controller - * - * Copyright (C) 2009 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * Based on wm97xx-core.c - */ - -#include -#include -#include -#include -#include -#include -#include - -/* Registers */ -#define MCS5000_TS_STATUS 0x00 -#define STATUS_OFFSET 0 -#define STATUS_NO (0 << STATUS_OFFSET) -#define STATUS_INIT (1 << STATUS_OFFSET) -#define STATUS_SENSING (2 << STATUS_OFFSET) -#define STATUS_COORD (3 << STATUS_OFFSET) -#define STATUS_GESTURE (4 << STATUS_OFFSET) -#define ERROR_OFFSET 4 -#define ERROR_NO (0 << ERROR_OFFSET) -#define ERROR_POWER_ON_RESET (1 << ERROR_OFFSET) -#define ERROR_INT_RESET (2 << ERROR_OFFSET) -#define ERROR_EXT_RESET (3 << ERROR_OFFSET) -#define ERROR_INVALID_REG_ADDRESS (8 << ERROR_OFFSET) -#define ERROR_INVALID_REG_VALUE (9 << ERROR_OFFSET) - -#define MCS5000_TS_OP_MODE 0x01 -#define RESET_OFFSET 0 -#define RESET_NO (0 << RESET_OFFSET) -#define RESET_EXT_SOFT (1 << RESET_OFFSET) -#define OP_MODE_OFFSET 1 -#define OP_MODE_SLEEP (0 << OP_MODE_OFFSET) -#define OP_MODE_ACTIVE (1 << OP_MODE_OFFSET) -#define GESTURE_OFFSET 4 -#define GESTURE_DISABLE (0 << GESTURE_OFFSET) -#define GESTURE_ENABLE (1 << GESTURE_OFFSET) -#define PROXIMITY_OFFSET 5 -#define PROXIMITY_DISABLE (0 << PROXIMITY_OFFSET) -#define PROXIMITY_ENABLE (1 << PROXIMITY_OFFSET) -#define SCAN_MODE_OFFSET 6 -#define SCAN_MODE_INTERRUPT (0 << SCAN_MODE_OFFSET) -#define SCAN_MODE_POLLING (1 << SCAN_MODE_OFFSET) -#define REPORT_RATE_OFFSET 7 -#define REPORT_RATE_40 (0 << REPORT_RATE_OFFSET) -#define REPORT_RATE_80 (1 << REPORT_RATE_OFFSET) - -#define MCS5000_TS_SENS_CTL 0x02 -#define MCS5000_TS_FILTER_CTL 0x03 -#define PRI_FILTER_OFFSET 0 -#define SEC_FILTER_OFFSET 4 - -#define MCS5000_TS_X_SIZE_UPPER 0x08 -#define MCS5000_TS_X_SIZE_LOWER 0x09 -#define MCS5000_TS_Y_SIZE_UPPER 0x0A -#define MCS5000_TS_Y_SIZE_LOWER 0x0B - -#define MCS5000_TS_INPUT_INFO 0x10 -#define INPUT_TYPE_OFFSET 0 -#define INPUT_TYPE_NONTOUCH (0 << INPUT_TYPE_OFFSET) -#define INPUT_TYPE_SINGLE (1 << INPUT_TYPE_OFFSET) -#define INPUT_TYPE_DUAL (2 << INPUT_TYPE_OFFSET) -#define INPUT_TYPE_PALM (3 << INPUT_TYPE_OFFSET) -#define INPUT_TYPE_PROXIMITY (7 << INPUT_TYPE_OFFSET) -#define GESTURE_CODE_OFFSET 3 -#define GESTURE_CODE_NO (0 << GESTURE_CODE_OFFSET) - -#define MCS5000_TS_X_POS_UPPER 0x11 -#define MCS5000_TS_X_POS_LOWER 0x12 -#define MCS5000_TS_Y_POS_UPPER 0x13 -#define MCS5000_TS_Y_POS_LOWER 0x14 -#define MCS5000_TS_Z_POS 0x15 -#define MCS5000_TS_WIDTH 0x16 -#define MCS5000_TS_GESTURE_VAL 0x17 -#define MCS5000_TS_MODULE_REV 0x20 -#define MCS5000_TS_FIRMWARE_VER 0x21 - -/* Touchscreen absolute values */ -#define MCS5000_MAX_XC 0x3ff -#define MCS5000_MAX_YC 0x3ff - -enum mcs5000_ts_read_offset { - READ_INPUT_INFO, - READ_X_POS_UPPER, - READ_X_POS_LOWER, - READ_Y_POS_UPPER, - READ_Y_POS_LOWER, - READ_BLOCK_SIZE, -}; - -/* Each client has this additional data */ -struct mcs5000_ts_data { - struct i2c_client *client; - struct input_dev *input_dev; - const struct mcs_platform_data *platform_data; -}; - -static irqreturn_t mcs5000_ts_interrupt(int irq, void *dev_id) -{ - struct mcs5000_ts_data *data = dev_id; - struct i2c_client *client = data->client; - u8 buffer[READ_BLOCK_SIZE]; - int err; - int x; - int y; - - err = i2c_smbus_read_i2c_block_data(client, MCS5000_TS_INPUT_INFO, - READ_BLOCK_SIZE, buffer); - if (err < 0) { - dev_err(&client->dev, "%s, err[%d]\n", __func__, err); - goto out; - } - - switch (buffer[READ_INPUT_INFO]) { - case INPUT_TYPE_NONTOUCH: - input_report_key(data->input_dev, BTN_TOUCH, 0); - input_sync(data->input_dev); - break; - - case INPUT_TYPE_SINGLE: - x = (buffer[READ_X_POS_UPPER] << 8) | buffer[READ_X_POS_LOWER]; - y = (buffer[READ_Y_POS_UPPER] << 8) | buffer[READ_Y_POS_LOWER]; - - input_report_key(data->input_dev, BTN_TOUCH, 1); - input_report_abs(data->input_dev, ABS_X, x); - input_report_abs(data->input_dev, ABS_Y, y); - input_sync(data->input_dev); - break; - - case INPUT_TYPE_DUAL: - /* TODO */ - break; - - case INPUT_TYPE_PALM: - /* TODO */ - break; - - case INPUT_TYPE_PROXIMITY: - /* TODO */ - break; - - default: - dev_err(&client->dev, "Unknown ts input type %d\n", - buffer[READ_INPUT_INFO]); - break; - } - - out: - return IRQ_HANDLED; -} - -static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data, - const struct mcs_platform_data *platform_data) -{ - struct i2c_client *client = data->client; - - /* Touch reset & sleep mode */ - i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, - RESET_EXT_SOFT | OP_MODE_SLEEP); - - /* Touch size */ - i2c_smbus_write_byte_data(client, MCS5000_TS_X_SIZE_UPPER, - platform_data->x_size >> 8); - i2c_smbus_write_byte_data(client, MCS5000_TS_X_SIZE_LOWER, - platform_data->x_size & 0xff); - i2c_smbus_write_byte_data(client, MCS5000_TS_Y_SIZE_UPPER, - platform_data->y_size >> 8); - i2c_smbus_write_byte_data(client, MCS5000_TS_Y_SIZE_LOWER, - platform_data->y_size & 0xff); - - /* Touch active mode & 80 report rate */ - i2c_smbus_write_byte_data(data->client, MCS5000_TS_OP_MODE, - OP_MODE_ACTIVE | REPORT_RATE_80); -} - -static int mcs5000_ts_probe(struct i2c_client *client) -{ - const struct mcs_platform_data *pdata; - struct mcs5000_ts_data *data; - struct input_dev *input_dev; - int error; - - pdata = dev_get_platdata(&client->dev); - if (!pdata) - return -EINVAL; - - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); - if (!data) { - dev_err(&client->dev, "Failed to allocate memory\n"); - return -ENOMEM; - } - - data->client = client; - - input_dev = devm_input_allocate_device(&client->dev); - if (!input_dev) { - dev_err(&client->dev, "Failed to allocate input device\n"); - return -ENOMEM; - } - - input_dev->name = "MELFAS MCS-5000 Touchscreen"; - input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &client->dev; - - __set_bit(EV_ABS, input_dev->evbit); - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(BTN_TOUCH, input_dev->keybit); - input_set_abs_params(input_dev, ABS_X, 0, MCS5000_MAX_XC, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, MCS5000_MAX_YC, 0, 0); - - data->input_dev = input_dev; - - if (pdata->cfg_pin) - pdata->cfg_pin(); - - error = devm_request_threaded_irq(&client->dev, client->irq, - NULL, mcs5000_ts_interrupt, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "mcs5000_ts", data); - if (error) { - dev_err(&client->dev, "Failed to register interrupt\n"); - return error; - } - - error = input_register_device(data->input_dev); - if (error) { - dev_err(&client->dev, "Failed to register input device\n"); - return error; - } - - mcs5000_ts_phys_init(data, pdata); - i2c_set_clientdata(client, data); - - return 0; -} - -static int mcs5000_ts_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - - /* Touch sleep mode */ - i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, OP_MODE_SLEEP); - - return 0; -} - -static int mcs5000_ts_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct mcs5000_ts_data *data = i2c_get_clientdata(client); - const struct mcs_platform_data *pdata = dev_get_platdata(dev); - - mcs5000_ts_phys_init(data, pdata); - - return 0; -} - -static DEFINE_SIMPLE_DEV_PM_OPS(mcs5000_ts_pm, - mcs5000_ts_suspend, mcs5000_ts_resume); - -static const struct i2c_device_id mcs5000_ts_id[] = { - { "mcs5000_ts" }, - { } -}; -MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); - -static struct i2c_driver mcs5000_ts_driver = { - .probe = mcs5000_ts_probe, - .driver = { - .name = "mcs5000_ts", - .pm = pm_sleep_ptr(&mcs5000_ts_pm), - }, - .id_table = mcs5000_ts_id, -}; - -module_i2c_driver(mcs5000_ts_driver); - -/* Module information */ -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_DESCRIPTION("Touchscreen driver for MELFAS MCS-5000 controller"); -MODULE_LICENSE("GPL"); diff --git a/include/linux/platform_data/mcs.h b/include/linux/platform_data/mcs.h index fcc6f2a1f5c3..f3b0749f1630 100644 --- a/include/linux/platform_data/mcs.h +++ b/include/linux/platform_data/mcs.h @@ -16,10 +16,6 @@ struct mcs_platform_data { void (*poweron)(bool); void (*cfg_pin)(void); - /* touchscreen */ - unsigned int x_size; - unsigned int y_size; - /* touchkey */ const u32 *keymap; unsigned int keymap_size; -- cgit v1.2.3 From dd29eadee1e8f07bbec57dddf4befbcd3e3c0af7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 13 Jul 2024 23:00:28 -0700 Subject: Input: msc_touchkey - remove the driver MCS-5000/5080 chips belong to the 1st generation of Melfas chips, manufactured in 2000-2007. The driver relies on custom platform data (no DT support) and there never were any users of this driver in the mainline kernel. It is likely that the driver was (like mcs5000_ts driver) was tested on S3C6410 NCP board (with Samsung S3C6410 SoC), but the touchkey device was never added to the board file. This board was removed in v6.3 in commit 743c8fbb90ca ("ARM: s3c: remove most s3c64xx board support"). Remove the driver since there are no users. Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240714060029.1528662-2-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 12 -- drivers/input/keyboard/Makefile | 1 - drivers/input/keyboard/mcs_touchkey.c | 268 ---------------------------------- include/linux/platform_data/mcs.h | 26 ---- 4 files changed, 307 deletions(-) delete mode 100644 drivers/input/keyboard/mcs_touchkey.c delete mode 100644 include/linux/platform_data/mcs.h (limited to 'include/linux/platform_data') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 1d0c5f4c0f99..72f9552cb571 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -421,18 +421,6 @@ config KEYBOARD_MAX7359 To compile this driver as a module, choose M here: the module will be called max7359_keypad. -config KEYBOARD_MCS - tristate "MELFAS MCS Touchkey" - depends on I2C - help - Say Y here if you have the MELFAS MCS5000/5080 touchkey controller - chip in your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called mcs_touchkey. - config KEYBOARD_MPR121 tristate "Freescale MPR121 Touchkey" depends on I2C diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index aecef00c5d09..b8d12a0524e0 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -41,7 +41,6 @@ obj-$(CONFIG_KEYBOARD_LPC32XX) += lpc32xx-keys.o obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o -obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o obj-$(CONFIG_KEYBOARD_MT6779) += mt6779-keypad.o obj-$(CONFIG_KEYBOARD_MTK_PMIC) += mtk-pmic-keys.o diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c deleted file mode 100644 index 2410f676c7f9..000000000000 --- a/drivers/input/keyboard/mcs_touchkey.c +++ /dev/null @@ -1,268 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Touchkey driver for MELFAS MCS5000/5080 controller - * - * Copyright (C) 2010 Samsung Electronics Co.Ltd - * Author: HeungJun Kim - * Author: Joonyoung Shim - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* MCS5000 Touchkey */ -#define MCS5000_TOUCHKEY_STATUS 0x04 -#define MCS5000_TOUCHKEY_STATUS_PRESS 7 -#define MCS5000_TOUCHKEY_FW 0x0a -#define MCS5000_TOUCHKEY_BASE_VAL 0x61 - -/* MCS5080 Touchkey */ -#define MCS5080_TOUCHKEY_STATUS 0x00 -#define MCS5080_TOUCHKEY_STATUS_PRESS 3 -#define MCS5080_TOUCHKEY_FW 0x01 -#define MCS5080_TOUCHKEY_BASE_VAL 0x1 - -enum mcs_touchkey_type { - MCS5000_TOUCHKEY, - MCS5080_TOUCHKEY, -}; - -struct mcs_touchkey_chip { - unsigned int status_reg; - unsigned int pressbit; - unsigned int press_invert; - unsigned int baseval; -}; - -struct mcs_touchkey_data { - void (*poweron)(bool); - - struct i2c_client *client; - struct input_dev *input_dev; - struct mcs_touchkey_chip chip; - unsigned int key_code; - unsigned int key_val; - unsigned short keycodes[]; -}; - -static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id) -{ - struct mcs_touchkey_data *data = dev_id; - struct mcs_touchkey_chip *chip = &data->chip; - struct i2c_client *client = data->client; - struct input_dev *input = data->input_dev; - unsigned int key_val; - unsigned int pressed; - int val; - - val = i2c_smbus_read_byte_data(client, chip->status_reg); - if (val < 0) { - dev_err(&client->dev, "i2c read error [%d]\n", val); - goto out; - } - - pressed = (val & (1 << chip->pressbit)) >> chip->pressbit; - if (chip->press_invert) - pressed ^= chip->press_invert; - - /* key_val is 0 when released, so we should use key_val of press. */ - if (pressed) { - key_val = val & (0xff >> (8 - chip->pressbit)); - if (!key_val) - goto out; - key_val -= chip->baseval; - data->key_code = data->keycodes[key_val]; - data->key_val = key_val; - } - - input_event(input, EV_MSC, MSC_SCAN, data->key_val); - input_report_key(input, data->key_code, pressed); - input_sync(input); - - dev_dbg(&client->dev, "key %d %d %s\n", data->key_val, data->key_code, - pressed ? "pressed" : "released"); - - out: - return IRQ_HANDLED; -} - -static void mcs_touchkey_poweroff(void *data) -{ - struct mcs_touchkey_data *touchkey = data; - - touchkey->poweron(false); -} - -static int mcs_touchkey_probe(struct i2c_client *client) -{ - const struct i2c_device_id *id = i2c_client_get_device_id(client); - const struct mcs_platform_data *pdata; - struct mcs_touchkey_data *data; - struct input_dev *input_dev; - unsigned int fw_reg; - int fw_ver; - int error; - int i; - - pdata = dev_get_platdata(&client->dev); - if (!pdata) { - dev_err(&client->dev, "no platform data defined\n"); - return -EINVAL; - } - - data = devm_kzalloc(&client->dev, - struct_size(data, keycodes, pdata->key_maxval + 1), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - input_dev = devm_input_allocate_device(&client->dev); - if (!input_dev) { - dev_err(&client->dev, "Failed to allocate input device\n"); - return -ENOMEM; - } - - data->client = client; - data->input_dev = input_dev; - - if (id->driver_data == MCS5000_TOUCHKEY) { - data->chip.status_reg = MCS5000_TOUCHKEY_STATUS; - data->chip.pressbit = MCS5000_TOUCHKEY_STATUS_PRESS; - data->chip.baseval = MCS5000_TOUCHKEY_BASE_VAL; - fw_reg = MCS5000_TOUCHKEY_FW; - } else { - data->chip.status_reg = MCS5080_TOUCHKEY_STATUS; - data->chip.pressbit = MCS5080_TOUCHKEY_STATUS_PRESS; - data->chip.press_invert = 1; - data->chip.baseval = MCS5080_TOUCHKEY_BASE_VAL; - fw_reg = MCS5080_TOUCHKEY_FW; - } - - fw_ver = i2c_smbus_read_byte_data(client, fw_reg); - if (fw_ver < 0) { - dev_err(&client->dev, "i2c read error[%d]\n", fw_ver); - return fw_ver; - } - dev_info(&client->dev, "Firmware version: %d\n", fw_ver); - - input_dev->name = "MELFAS MCS Touchkey"; - input_dev->id.bustype = BUS_I2C; - input_dev->evbit[0] = BIT_MASK(EV_KEY); - if (!pdata->no_autorepeat) - input_dev->evbit[0] |= BIT_MASK(EV_REP); - input_dev->keycode = data->keycodes; - input_dev->keycodesize = sizeof(data->keycodes[0]); - input_dev->keycodemax = pdata->key_maxval + 1; - - for (i = 0; i < pdata->keymap_size; i++) { - unsigned int val = MCS_KEY_VAL(pdata->keymap[i]); - unsigned int code = MCS_KEY_CODE(pdata->keymap[i]); - - data->keycodes[val] = code; - __set_bit(code, input_dev->keybit); - } - - input_set_capability(input_dev, EV_MSC, MSC_SCAN); - input_set_drvdata(input_dev, data); - - if (pdata->cfg_pin) - pdata->cfg_pin(); - - if (pdata->poweron) { - data->poweron = pdata->poweron; - data->poweron(true); - - error = devm_add_action_or_reset(&client->dev, - mcs_touchkey_poweroff, data); - if (error) - return error; - } - - error = devm_request_threaded_irq(&client->dev, client->irq, - NULL, mcs_touchkey_interrupt, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - client->dev.driver->name, data); - if (error) { - dev_err(&client->dev, "Failed to register interrupt\n"); - return error; - } - - error = input_register_device(input_dev); - if (error) - return error; - - i2c_set_clientdata(client, data); - return 0; -} - -static void mcs_touchkey_shutdown(struct i2c_client *client) -{ - struct mcs_touchkey_data *data = i2c_get_clientdata(client); - - if (data->poweron) - data->poweron(false); -} - -static int mcs_touchkey_suspend(struct device *dev) -{ - struct mcs_touchkey_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - - /* Disable the work */ - disable_irq(client->irq); - - /* Finally turn off the power */ - if (data->poweron) - data->poweron(false); - - return 0; -} - -static int mcs_touchkey_resume(struct device *dev) -{ - struct mcs_touchkey_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - - /* Enable the device first */ - if (data->poweron) - data->poweron(true); - - /* Enable irq again */ - enable_irq(client->irq); - - return 0; -} - -static DEFINE_SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops, - mcs_touchkey_suspend, mcs_touchkey_resume); - -static const struct i2c_device_id mcs_touchkey_id[] = { - { "mcs5000_touchkey", MCS5000_TOUCHKEY }, - { "mcs5080_touchkey", MCS5080_TOUCHKEY }, - { } -}; -MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id); - -static struct i2c_driver mcs_touchkey_driver = { - .driver = { - .name = "mcs_touchkey", - .pm = pm_sleep_ptr(&mcs_touchkey_pm_ops), - }, - .probe = mcs_touchkey_probe, - .shutdown = mcs_touchkey_shutdown, - .id_table = mcs_touchkey_id, -}; - -module_i2c_driver(mcs_touchkey_driver); - -/* Module information */ -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_AUTHOR("HeungJun Kim "); -MODULE_DESCRIPTION("Touchkey driver for MELFAS MCS5000/5080 controller"); -MODULE_LICENSE("GPL"); diff --git a/include/linux/platform_data/mcs.h b/include/linux/platform_data/mcs.h deleted file mode 100644 index f3b0749f1630..000000000000 --- a/include/linux/platform_data/mcs.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2009 - 2010 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * Author: HeungJun Kim - */ - -#ifndef __LINUX_MCS_H -#define __LINUX_MCS_H - -#define MCS_KEY_MAP(v, c) ((((v) & 0xff) << 16) | ((c) & 0xffff)) -#define MCS_KEY_VAL(v) (((v) >> 16) & 0xff) -#define MCS_KEY_CODE(v) ((v) & 0xffff) - -struct mcs_platform_data { - void (*poweron)(bool); - void (*cfg_pin)(void); - - /* touchkey */ - const u32 *keymap; - unsigned int keymap_size; - unsigned int key_maxval; - bool no_autorepeat; -}; - -#endif /* __LINUX_MCS_H */ -- cgit v1.2.3 From 45b8ee7182d5ef8df6959297046f86dc128d6a06 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Mon, 17 Jun 2024 14:08:18 +0200 Subject: i2c: mux: gpio: Add support for the 'settle-time-us' property Some hardware need some time to switch from a bus to another. This can cause the first transfers following the selection of a bus to fail. There is no way to configure this kind of waiting time in the driver. Add support for the 'settle-time-us' device-tree property. When set, the i2c_mux_gpio_select() applies a delay before returning, leaving enough time to the hardware to switch to the new bus. Signed-off-by: Bastien Curutchet Reviewed-by: Andi Shyti Acked-by: Peter Rosin Signed-off-by: Andi Shyti --- drivers/i2c/muxes/i2c-mux-gpio.c | 6 ++++++ include/linux/platform_data/i2c-mux-gpio.h | 2 ++ 2 files changed, 8 insertions(+) (limited to 'include/linux/platform_data') diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index c61e9d9ea695..944577bb09c1 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -37,6 +38,9 @@ static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan) i2c_mux_gpio_set(mux, chan); + if (mux->data.settle_time) + fsleep(mux->data.settle_time); + return 0; } @@ -116,6 +120,8 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux, if (device_property_read_u32(dev, "idle-state", &mux->data.idle)) mux->data.idle = I2C_MUX_GPIO_NO_IDLE; + device_property_read_u32(dev, "settle-time-us", &mux->data.settle_time); + return 0; } diff --git a/include/linux/platform_data/i2c-mux-gpio.h b/include/linux/platform_data/i2c-mux-gpio.h index 816a4cd3ccb5..96843aab4d1e 100644 --- a/include/linux/platform_data/i2c-mux-gpio.h +++ b/include/linux/platform_data/i2c-mux-gpio.h @@ -19,6 +19,7 @@ * position * @n_values: Number of multiplexer positions (busses to instantiate) * @idle: Bitmask to write to MUX when idle or GPIO_I2CMUX_NO_IDLE if not used + * @settle_time: Delay to wait when a new bus is selected */ struct i2c_mux_gpio_platform_data { int parent; @@ -26,6 +27,7 @@ struct i2c_mux_gpio_platform_data { const unsigned *values; int n_values; unsigned idle; + u32 settle_time; }; #endif /* _LINUX_I2C_MUX_GPIO_H */ -- cgit v1.2.3 From f81489a136ac2c18a7b9bb22cf37c0a6f6d58545 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 12 Jul 2024 13:57:13 -0700 Subject: hwmon: (max6697) Drop platform data support Platform data is not used anywhere in the upstram kernel. Drop support for it to simplify code maintenance. Reviewed-by: Tzung-Bi Shih Signed-off-by: Guenter Roeck --- drivers/hwmon/max6697.c | 176 ++++++++++++++++------------------ include/linux/platform_data/max6697.h | 33 ------- 2 files changed, 82 insertions(+), 127 deletions(-) delete mode 100644 include/linux/platform_data/max6697.h (limited to 'include/linux/platform_data') diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c index 9a2a21230c7d..b9766533d876 100644 --- a/drivers/hwmon/max6697.c +++ b/drivers/hwmon/max6697.c @@ -17,8 +17,6 @@ #include #include -#include - enum chips { max6581, max6602, max6622, max6636, max6689, max6693, max6694, max6697, max6698, max6699 }; @@ -558,54 +556,97 @@ static const struct attribute_group max6697_group = { }; __ATTRIBUTE_GROUPS(max6697); -static void max6697_get_config_of(struct device_node *node, - struct max6697_platform_data *pdata) +static int max6697_config_of(struct max6697_data *data, struct i2c_client *client) { - int len; - const __be32 *prop; - - pdata->smbus_timeout_disable = - of_property_read_bool(node, "smbus-timeout-disable"); - pdata->extended_range_enable = - of_property_read_bool(node, "extended-range-enable"); - pdata->beta_compensation = - of_property_read_bool(node, "beta-compensation-enable"); - - prop = of_get_property(node, "alert-mask", &len); - if (prop && len == sizeof(u32)) - pdata->alert_mask = be32_to_cpu(prop[0]); - prop = of_get_property(node, "over-temperature-mask", &len); - if (prop && len == sizeof(u32)) - pdata->over_temperature_mask = be32_to_cpu(prop[0]); - prop = of_get_property(node, "resistance-cancellation", &len); - if (prop) { - if (len == sizeof(u32)) - pdata->resistance_cancellation = be32_to_cpu(prop[0]); - else - pdata->resistance_cancellation = 0xfe; + const struct max6697_chip_data *chip = data->chip; + struct device_node *node = client->dev.of_node; + int ret, confreg; + int factor = 0; + u32 vals[2]; + + confreg = 0; + if (of_property_read_bool(node, "smbus-timeout-disable") && + (chip->valid_conf & MAX6697_CONF_TIMEOUT)) { + confreg |= MAX6697_CONF_TIMEOUT; + } + if (of_property_read_bool(node, "extended-range-enable") && + (chip->valid_conf & MAX6581_CONF_EXTENDED)) { + confreg |= MAX6581_CONF_EXTENDED; + data->temp_offset = 64; + } + if (of_property_read_bool(node, "beta-compensation-enable") && + (chip->valid_conf & MAX6693_CONF_BETA)) { + confreg |= MAX6693_CONF_BETA; } - prop = of_get_property(node, "transistor-ideality", &len); - if (prop && len == 2 * sizeof(u32)) { - pdata->ideality_mask = be32_to_cpu(prop[0]); - pdata->ideality_value = be32_to_cpu(prop[1]); + + if (of_property_read_u32(node, "alert-mask", vals)) + vals[0] = 0; + ret = i2c_smbus_write_byte_data(client, MAX6697_REG_ALERT_MASK, + MAX6697_ALERT_MAP_BITS(vals[0])); + if (ret) + return ret; + + if (of_property_read_u32(node, "over-temperature-mask", vals)) + vals[0] = 0; + ret = i2c_smbus_write_byte_data(client, MAX6697_REG_OVERT_MASK, + MAX6697_OVERT_MAP_BITS(vals[0])); + if (ret) + return ret; + + if (data->type != max6581) { + if (of_property_read_bool(node, "resistance-cancellation") && + chip->valid_conf & MAX6697_CONF_RESISTANCE) { + confreg |= MAX6697_CONF_RESISTANCE; + factor = 1; + } + } else { + if (of_property_read_u32(node, "resistance-cancellation", &vals[0])) { + if (of_property_read_bool(node, "resistance-cancellation")) + vals[0] = 0xfe; + else + vals[0] = 0; + } + + vals[0] &= 0xfe; + factor = hweight8(vals[0]); + ret = i2c_smbus_write_byte_data(client, MAX6581_REG_RESISTANCE, + vals[0] >> 1); + if (ret < 0) + return ret; + + if (of_property_read_u32_array(node, "transistor-ideality", vals, 2)) { + vals[0] = 0; + vals[1] = 0; + } + + ret = i2c_smbus_write_byte_data(client, MAX6581_REG_IDEALITY, + vals[1]); + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(client, + MAX6581_REG_IDEALITY_SELECT, + (vals[0] & 0xfe) >> 1); + if (ret < 0) + return ret; } + ret = i2c_smbus_write_byte_data(client, MAX6697_REG_CONFIG, confreg); + if (ret < 0) + return ret; + return factor; } static int max6697_init_chip(struct max6697_data *data, struct i2c_client *client) { - struct max6697_platform_data *pdata = dev_get_platdata(&client->dev); - struct max6697_platform_data p; const struct max6697_chip_data *chip = data->chip; int factor = chip->channels; int ret, reg; /* - * Don't touch configuration if neither platform data nor OF - * configuration was specified. If that is the case, use the - * current chip configuration. + * Don't touch configuration if there is no devicetree configuration. + * If that is the case, use the current chip configuration. */ - if (!pdata && !client->dev.of_node) { + if (!client->dev.of_node) { reg = i2c_smbus_read_byte_data(client, MAX6697_REG_CONFIG); if (reg < 0) return reg; @@ -621,67 +662,14 @@ static int max6697_init_chip(struct max6697_data *data, if (reg & MAX6697_CONF_RESISTANCE) factor++; } - goto done; - } - - if (client->dev.of_node) { - memset(&p, 0, sizeof(p)); - max6697_get_config_of(client->dev.of_node, &p); - pdata = &p; - } - - reg = 0; - if (pdata->smbus_timeout_disable && - (chip->valid_conf & MAX6697_CONF_TIMEOUT)) { - reg |= MAX6697_CONF_TIMEOUT; - } - if (pdata->extended_range_enable && - (chip->valid_conf & MAX6581_CONF_EXTENDED)) { - reg |= MAX6581_CONF_EXTENDED; - data->temp_offset = 64; - } - if (pdata->resistance_cancellation && - (chip->valid_conf & MAX6697_CONF_RESISTANCE)) { - reg |= MAX6697_CONF_RESISTANCE; - factor++; - } - if (pdata->beta_compensation && - (chip->valid_conf & MAX6693_CONF_BETA)) { - reg |= MAX6693_CONF_BETA; - } - - ret = i2c_smbus_write_byte_data(client, MAX6697_REG_CONFIG, reg); - if (ret < 0) - return ret; - - ret = i2c_smbus_write_byte_data(client, MAX6697_REG_ALERT_MASK, - MAX6697_ALERT_MAP_BITS(pdata->alert_mask)); - if (ret < 0) - return ret; - - ret = i2c_smbus_write_byte_data(client, MAX6697_REG_OVERT_MASK, - MAX6697_OVERT_MAP_BITS(pdata->over_temperature_mask)); - if (ret < 0) - return ret; - - if (data->type == max6581) { - factor += hweight8(pdata->resistance_cancellation >> 1); - ret = i2c_smbus_write_byte_data(client, MAX6581_REG_RESISTANCE, - pdata->resistance_cancellation >> 1); - if (ret < 0) - return ret; - ret = i2c_smbus_write_byte_data(client, MAX6581_REG_IDEALITY, - pdata->ideality_value); - if (ret < 0) - return ret; - ret = i2c_smbus_write_byte_data(client, - MAX6581_REG_IDEALITY_SELECT, - pdata->ideality_mask >> 1); + data->update_interval = factor * MAX6697_CONV_TIME; + } else { + ret = max6697_config_of(data, client); if (ret < 0) return ret; + data->update_interval = (factor + ret) * MAX6697_CONV_TIME; } -done: - data->update_interval = factor * MAX6697_CONV_TIME; + return 0; } diff --git a/include/linux/platform_data/max6697.h b/include/linux/platform_data/max6697.h deleted file mode 100644 index 6fbb70005541..000000000000 --- a/include/linux/platform_data/max6697.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * max6697.h - * Copyright (c) 2012 Guenter Roeck - */ - -#ifndef MAX6697_H -#define MAX6697_H - -#include - -/* - * For all bit masks: - * bit 0: local temperature - * bit 1..7: remote temperatures - */ -struct max6697_platform_data { - bool smbus_timeout_disable; /* set to disable SMBus timeouts */ - bool extended_range_enable; /* set to enable extended temp range */ - bool beta_compensation; /* set to enable beta compensation */ - u8 alert_mask; /* set bit to 1 to disable alert */ - u8 over_temperature_mask; /* set bit to 1 to disable */ - u8 resistance_cancellation; /* set bit to 0 to disable - * bit mask for MAX6581, - * boolean for other chips - */ - u8 ideality_mask; /* set bit to 0 to disable */ - u8 ideality_value; /* transistor ideality as per - * MAX6581 datasheet - */ -}; - -#endif /* MAX6697_H */ -- cgit v1.2.3 From bcbfcebda2cbc6a10a347d726e4a4f69e43a864e Mon Sep 17 00:00:00 2001 From: Mohamed Ghanmi Date: Sun, 9 Jun 2024 15:48:49 +0100 Subject: platform/x86: asus-wmi: add support for vivobook fan profiles Add support for vivobook fan profiles wmi call on the ASUS VIVOBOOK to adjust power limits. These fan profiles have a different device id than the ROG series and different order. This reorders the existing modes. As part of keeping the patch clean the throttle_thermal_policy_available boolean stored in the driver struct is removed and throttle_thermal_policy_dev is used in place (as on init it is zeroed). Co-developed-by: Luke D. Jones Signed-off-by: Luke D. Jones Signed-off-by: Mohamed Ghanmi Reviewed-by: Luke D. Jones Link: https://lore.kernel.org/r/20240609144849.2532-2-mohamed.ghanmi@supcom.tn Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/asus-wmi.c | 120 +++++++++++++++++------------ include/linux/platform_data/x86/asus-wmi.h | 1 + 2 files changed, 71 insertions(+), 50 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index cc735931f97b..00669cf678fb 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -97,6 +97,12 @@ module_param(fnlock_default, bool, 0444); #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST 1 #define ASUS_THROTTLE_THERMAL_POLICY_SILENT 2 +#define ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO 0 +#define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO 1 +#define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO 2 + +#define PLATFORM_PROFILE_MAX 2 + #define USB_INTEL_XUSB2PR 0xD0 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 @@ -286,8 +292,8 @@ struct asus_wmi { u32 kbd_rgb_dev; bool kbd_rgb_state_available; - bool throttle_thermal_policy_available; u8 throttle_thermal_policy_mode; + u32 throttle_thermal_policy_dev; bool cpu_fan_curve_available; bool gpu_fan_curve_available; @@ -3162,7 +3168,7 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev) int err, fan_idx; u8 mode = 0; - if (asus->throttle_thermal_policy_available) + if (asus->throttle_thermal_policy_dev) mode = asus->throttle_thermal_policy_mode; /* DEVID_PU_FAN_CURVE is switched for OVERBOOST vs SILENT */ if (mode == 2) @@ -3369,7 +3375,7 @@ static ssize_t fan_curve_enable_store(struct device *dev, * For machines with throttle this is the only way to reset fans * to default mode of operation (does not erase curve data). */ - if (asus->throttle_thermal_policy_available) { + if (asus->throttle_thermal_policy_dev) { err = throttle_thermal_policy_write(asus); if (err) return err; @@ -3586,8 +3592,8 @@ static const struct attribute_group asus_fan_curve_attr_group = { __ATTRIBUTE_GROUPS(asus_fan_curve_attr); /* - * Must be initialised after throttle_thermal_policy_check_present() as - * we check the status of throttle_thermal_policy_available during init. + * Must be initialised after throttle_thermal_policy_dev is set as + * we check the status of throttle_thermal_policy_dev during init. */ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) { @@ -3628,38 +3634,13 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) } /* Throttle thermal policy ****************************************************/ - -static int throttle_thermal_policy_check_present(struct asus_wmi *asus) -{ - u32 result; - int err; - - asus->throttle_thermal_policy_available = false; - - err = asus_wmi_get_devstate(asus, - ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, - &result); - if (err) { - if (err == -ENODEV) - return 0; - return err; - } - - if (result & ASUS_WMI_DSTS_PRESENCE_BIT) - asus->throttle_thermal_policy_available = true; - - return 0; -} - static int throttle_thermal_policy_write(struct asus_wmi *asus) { - int err; - u8 value; + u8 value = asus->throttle_thermal_policy_mode; u32 retval; + int err; - value = asus->throttle_thermal_policy_mode; - - err = asus_wmi_set_devstate(ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, + err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev, value, &retval); sysfs_notify(&asus->platform_device->dev.kobj, NULL, @@ -3689,7 +3670,7 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus) static int throttle_thermal_policy_set_default(struct asus_wmi *asus) { - if (!asus->throttle_thermal_policy_available) + if (!asus->throttle_thermal_policy_dev) return 0; asus->throttle_thermal_policy_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; @@ -3701,7 +3682,7 @@ static int throttle_thermal_policy_switch_next(struct asus_wmi *asus) u8 new_mode = asus->throttle_thermal_policy_mode + 1; int err; - if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT) + if (new_mode > PLATFORM_PROFILE_MAX) new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; asus->throttle_thermal_policy_mode = new_mode; @@ -3740,7 +3721,7 @@ static ssize_t throttle_thermal_policy_store(struct device *dev, if (result < 0) return result; - if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT) + if (new_mode > PLATFORM_PROFILE_MAX) return -EINVAL; asus->throttle_thermal_policy_mode = new_mode; @@ -3757,10 +3738,52 @@ static ssize_t throttle_thermal_policy_store(struct device *dev, return count; } -// Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent +/* + * Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent + */ static DEVICE_ATTR_RW(throttle_thermal_policy); /* Platform profile ***********************************************************/ +static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus, int mode) +{ + bool vivo; + + vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; + + if (vivo) { + switch (mode) { + case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: + return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO; + case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST: + return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO; + case ASUS_THROTTLE_THERMAL_POLICY_SILENT: + return ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO; + } + } + + return mode; +} + +static int asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int mode) +{ + bool vivo; + + vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; + + if (vivo) { + switch (mode) { + case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO: + return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; + case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO: + return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST; + case ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO: + return ASUS_THROTTLE_THERMAL_POLICY_SILENT; + } + } + + return mode; +} + static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof, enum platform_profile_option *profile) { @@ -3768,10 +3791,9 @@ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof, int tp; asus = container_of(pprof, struct asus_wmi, platform_profile_handler); - tp = asus->throttle_thermal_policy_mode; - switch (tp) { + switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) { case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: *profile = PLATFORM_PROFILE_BALANCED; break; @@ -3810,7 +3832,7 @@ static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof, return -EOPNOTSUPP; } - asus->throttle_thermal_policy_mode = tp; + asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp); return throttle_thermal_policy_write(asus); } @@ -3823,7 +3845,7 @@ static int platform_profile_setup(struct asus_wmi *asus) * Not an error if a component platform_profile relies on is unavailable * so early return, skipping the setup of platform_profile. */ - if (!asus->throttle_thermal_policy_available) + if (!asus->throttle_thermal_policy_dev) return 0; dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n"); @@ -4238,7 +4260,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) if (code == NOTIFY_KBD_FBM || code == NOTIFY_KBD_TTP) { if (asus->fan_boost_mode_available) fan_boost_mode_switch_next(asus); - if (asus->throttle_thermal_policy_available) + if (asus->throttle_thermal_policy_dev) throttle_thermal_policy_switch_next(asus); return; @@ -4410,7 +4432,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, else if (attr == &dev_attr_fan_boost_mode.attr) ok = asus->fan_boost_mode_available; else if (attr == &dev_attr_throttle_thermal_policy.attr) - ok = asus->throttle_thermal_policy_available; + ok = asus->throttle_thermal_policy_dev != 0; else if (attr == &dev_attr_ppt_pl2_sppt.attr) devid = ASUS_WMI_DEVID_PPT_PL2_SPPT; else if (attr == &dev_attr_ppt_pl1_spl.attr) @@ -4702,16 +4724,15 @@ static int asus_wmi_add(struct platform_device *pdev) else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE2)) asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE2; + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY)) + asus->throttle_thermal_policy_dev = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY; + else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO)) + asus->throttle_thermal_policy_dev = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; + err = fan_boost_mode_check_present(asus); if (err) goto fail_fan_boost_mode; - err = throttle_thermal_policy_check_present(asus); - if (err) - goto fail_throttle_thermal_policy; - else - throttle_thermal_policy_set_default(asus); - err = platform_profile_setup(asus); if (err) goto fail_platform_profile_setup; @@ -4806,7 +4827,6 @@ fail_hwmon: fail_input: asus_wmi_sysfs_exit(asus->platform_device); fail_sysfs: -fail_throttle_thermal_policy: fail_custom_fan_curve: fail_platform_profile_setup: if (asus->platform_profile_support) diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 0aeeae1c1943..5e6f407b2def 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -68,6 +68,7 @@ #define ASUS_WMI_DEVID_SCREENPAD_LIGHT 0x00050032 #define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018 #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075 +#define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO 0x00110019 /* Misc */ #define ASUS_WMI_DEVID_PANEL_OD 0x00050019 -- cgit v1.2.3 From a720dee5e039238a44c0142dfccdc0e35c1125f7 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Sat, 13 Jul 2024 19:47:33 +1200 Subject: hid-asus: use hid for brightness control on keyboard On almost all ASUS ROG series laptops the MCU used for the USB keyboard also has a HID packet used for setting the brightness. This is usually the same as the WMI method. But in some laptops the WMI method either is missing or doesn't work, so we should default to the HID control. Signed-off-by: Luke D. Jones Acked-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20240713074733.77334-2-luke@ljones.dev Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/hid/hid-asus.c | 7 ++++++ drivers/platform/x86/asus-wmi.c | 3 ++- include/linux/platform_data/x86/asus-wmi.h | 36 ++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) (limited to 'include/linux/platform_data') diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index 37e6d25593c2..af57a5f03193 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -492,12 +492,19 @@ static void asus_kbd_backlight_work(struct work_struct *work) */ static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev) { + struct asus_drvdata *drvdata = hid_get_drvdata(hdev); u32 value; int ret; if (!IS_ENABLED(CONFIG_ASUS_WMI)) return false; + if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD && + dmi_check_system(asus_use_hid_led_dmi_ids)) { + hid_info(hdev, "using HID for asus::kbd_backlight\n"); + return false; + } + ret = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, &value); hid_dbg(hdev, "WMI backlight check: rc %d value %x", ret, value); diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 00669cf678fb..35ebb37f68bf 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1714,7 +1714,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } - if (!kbd_led_read(asus, &led_val, NULL)) { + if (!kbd_led_read(asus, &led_val, NULL) && !dmi_check_system(asus_use_hid_led_dmi_ids)) { + pr_info("using asus-wmi for asus::kbd_backlight\n"); asus->kbd_led_wk = led_val; asus->kbd_led.name = "asus::kbd_backlight"; asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED; diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 5e6f407b2def..b601b245a035 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -4,6 +4,7 @@ #include #include +#include /* WMI Methods */ #define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */ @@ -165,4 +166,39 @@ static inline int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, } #endif +/* To be used by both hid-asus and asus-wmi to determine which controls kbd_brightness */ +static const struct dmi_system_id asus_use_hid_led_dmi_ids[] = { + { + .matches = { + DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Zephyrus"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Strix"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Flow"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GA403U"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GU605M"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "RC71L"), + }, + }, + { }, +}; + #endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */ -- cgit v1.2.3 From 25162a4f64f8ba0065f300977589fe1f6af332f0 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 4 Aug 2024 17:16:25 -0700 Subject: Input: cyttsp4 - remove driver The cyttsp4 touchscreen driver was contributed in 2013 and since then has seen no updates. The driver uses platform data (no device tree support) and there are no users of it in the mainline kernel. There were occasional fixes to it for issues either found by static code analysis tools or via visual inspection, but otherwise the driver is completely untested. Remove the driver. Reviewed-by: Linus Walleij Reviewed-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/ZrAZ2cUow_z838tp@google.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 30 - drivers/input/touchscreen/Makefile | 5 +- drivers/input/touchscreen/cyttsp4_core.c | 2174 ------------------------- drivers/input/touchscreen/cyttsp4_core.h | 448 ----- drivers/input/touchscreen/cyttsp4_i2c.c | 72 - drivers/input/touchscreen/cyttsp4_spi.c | 187 --- drivers/input/touchscreen/cyttsp_core.h | 4 - drivers/input/touchscreen/cyttsp_i2c.c | 55 + drivers/input/touchscreen/cyttsp_i2c_common.c | 86 - include/linux/platform_data/cyttsp4.h | 62 - 10 files changed, 56 insertions(+), 3067 deletions(-) delete mode 100644 drivers/input/touchscreen/cyttsp4_core.c delete mode 100644 drivers/input/touchscreen/cyttsp4_core.h delete mode 100644 drivers/input/touchscreen/cyttsp4_i2c.c delete mode 100644 drivers/input/touchscreen/cyttsp4_spi.c delete mode 100644 drivers/input/touchscreen/cyttsp_i2c_common.c delete mode 100644 include/linux/platform_data/cyttsp4.h (limited to 'include/linux/platform_data') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 0df90c3d743b..1ac26fc2e3eb 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -254,36 +254,6 @@ config TOUCHSCREEN_CYTTSP_SPI To compile this driver as a module, choose M here: the module will be called cyttsp_spi. -config TOUCHSCREEN_CYTTSP4_CORE - tristate "Cypress TrueTouch Gen4 Touchscreen Driver" - help - Core driver for Cypress TrueTouch(tm) Standard Product - Generation4 touchscreen controllers. - - Say Y here if you have a Cypress Gen4 touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here. - -config TOUCHSCREEN_CYTTSP4_I2C - tristate "support I2C bus connection" - depends on TOUCHSCREEN_CYTTSP4_CORE && I2C - help - Say Y here if the touchscreen is connected via I2C bus. - - To compile this driver as a module, choose M here: the - module will be called cyttsp4_i2c. - -config TOUCHSCREEN_CYTTSP4_SPI - tristate "support SPI bus connection" - depends on TOUCHSCREEN_CYTTSP4_CORE && SPI_MASTER - help - Say Y here if the touchscreen is connected via SPI bus. - - To compile this driver as a module, choose M here: the - module will be called cyttsp4_spi. - config TOUCHSCREEN_CYTTSP5 tristate "Cypress TrueTouch Gen5 Touchscreen Driver" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 04dc8039341b..82bc837ca01e 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -25,11 +25,8 @@ obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8505) += chipone_icn8505.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMA140) += cy8ctma140.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o cyttsp_i2c_common.o +obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_CORE) += cyttsp4_core.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_I2C) += cyttsp4_i2c.o cyttsp_i2c_common.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_SPI) += cyttsp4_spi.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP5) += cyttsp5.o obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c deleted file mode 100644 index 7cb26929dc73..000000000000 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ /dev/null @@ -1,2174 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cyttsp4_core.c - * Cypress TrueTouch(TM) Standard Product V4 Core driver module. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2012 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com - */ - -#include "cyttsp4_core.h" -#include -#include -#include -#include -#include -#include -#include - -/* Timeout in ms. */ -#define CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT 500 -#define CY_CORE_SLEEP_REQUEST_EXCLUSIVE_TIMEOUT 5000 -#define CY_CORE_MODE_CHANGE_TIMEOUT 1000 -#define CY_CORE_RESET_AND_WAIT_TIMEOUT 500 -#define CY_CORE_WAKEUP_TIMEOUT 500 - -#define CY_CORE_STARTUP_RETRY_COUNT 3 - -static const char * const cyttsp4_tch_abs_string[] = { - [CY_TCH_X] = "X", - [CY_TCH_Y] = "Y", - [CY_TCH_P] = "P", - [CY_TCH_T] = "T", - [CY_TCH_E] = "E", - [CY_TCH_O] = "O", - [CY_TCH_W] = "W", - [CY_TCH_MAJ] = "MAJ", - [CY_TCH_MIN] = "MIN", - [CY_TCH_OR] = "OR", - [CY_TCH_NUM_ABS] = "INVALID" -}; - -static const u8 ldr_exit[] = { - 0xFF, 0x01, 0x3B, 0x00, 0x00, 0x4F, 0x6D, 0x17 -}; - -static const u8 ldr_err_app[] = { - 0x01, 0x02, 0x00, 0x00, 0x55, 0xDD, 0x17 -}; - -static inline size_t merge_bytes(u8 high, u8 low) -{ - return (high << 8) + low; -} - -#ifdef VERBOSE_DEBUG -static void cyttsp4_pr_buf(struct device *dev, u8 *pr_buf, u8 *dptr, int size, - const char *data_name) -{ - int i, k; - const char fmt[] = "%02X "; - int max; - - if (!size) - return; - - max = (CY_MAX_PRBUF_SIZE - 1) - sizeof(CY_PR_TRUNCATED); - - pr_buf[0] = 0; - for (i = k = 0; i < size && k < max; i++, k += 3) - scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, fmt, dptr[i]); - - dev_vdbg(dev, "%s: %s[0..%d]=%s%s\n", __func__, data_name, size - 1, - pr_buf, size <= max ? "" : CY_PR_TRUNCATED); -} -#else -#define cyttsp4_pr_buf(dev, pr_buf, dptr, size, data_name) do { } while (0) -#endif - -static int cyttsp4_load_status_regs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - struct device *dev = cd->dev; - int rc; - - rc = cyttsp4_adap_read(cd, CY_REG_BASE, si->si_ofs.mode_size, - si->xy_mode); - if (rc < 0) - dev_err(dev, "%s: fail read mode regs r=%d\n", - __func__, rc); - else - cyttsp4_pr_buf(dev, cd->pr_buf, si->xy_mode, - si->si_ofs.mode_size, "xy_mode"); - - return rc; -} - -static int cyttsp4_handshake(struct cyttsp4 *cd, u8 mode) -{ - u8 cmd = mode ^ CY_HST_TOGGLE; - int rc; - - /* - * Mode change issued, handshaking now will cause endless mode change - * requests, for sync mode modechange will do same with handshake - * */ - if (mode & CY_HST_MODE_CHANGE) - return 0; - - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(cmd), &cmd); - if (rc < 0) - dev_err(cd->dev, "%s: bus write fail on handshake (ret=%d)\n", - __func__, rc); - - return rc; -} - -static int cyttsp4_hw_soft_reset(struct cyttsp4 *cd) -{ - u8 cmd = CY_HST_RESET; - int rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(cmd), &cmd); - if (rc < 0) { - dev_err(cd->dev, "%s: FAILED to execute SOFT reset\n", - __func__); - return rc; - } - return 0; -} - -static int cyttsp4_hw_hard_reset(struct cyttsp4 *cd) -{ - if (cd->cpdata->xres) { - cd->cpdata->xres(cd->cpdata, cd->dev); - dev_dbg(cd->dev, "%s: execute HARD reset\n", __func__); - return 0; - } - dev_err(cd->dev, "%s: FAILED to execute HARD reset\n", __func__); - return -ENOSYS; -} - -static int cyttsp4_hw_reset(struct cyttsp4 *cd) -{ - int rc = cyttsp4_hw_hard_reset(cd); - if (rc == -ENOSYS) - rc = cyttsp4_hw_soft_reset(cd); - return rc; -} - -/* - * Gets number of bits for a touch filed as parameter, - * sets maximum value for field which is used as bit mask - * and returns number of bytes required for that field - */ -static int cyttsp4_bits_2_bytes(unsigned int nbits, size_t *max) -{ - *max = 1UL << nbits; - return (nbits + 7) / 8; -} - -static int cyttsp4_si_data_offsets(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(si->si_data), - &si->si_data); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read sysinfo data offsets r=%d\n", - __func__, rc); - return rc; - } - - /* Print sysinfo data offsets */ - cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)&si->si_data, - sizeof(si->si_data), "sysinfo_data_offsets"); - - /* convert sysinfo data offset bytes into integers */ - - si->si_ofs.map_sz = merge_bytes(si->si_data.map_szh, - si->si_data.map_szl); - si->si_ofs.map_sz = merge_bytes(si->si_data.map_szh, - si->si_data.map_szl); - si->si_ofs.cydata_ofs = merge_bytes(si->si_data.cydata_ofsh, - si->si_data.cydata_ofsl); - si->si_ofs.test_ofs = merge_bytes(si->si_data.test_ofsh, - si->si_data.test_ofsl); - si->si_ofs.pcfg_ofs = merge_bytes(si->si_data.pcfg_ofsh, - si->si_data.pcfg_ofsl); - si->si_ofs.opcfg_ofs = merge_bytes(si->si_data.opcfg_ofsh, - si->si_data.opcfg_ofsl); - si->si_ofs.ddata_ofs = merge_bytes(si->si_data.ddata_ofsh, - si->si_data.ddata_ofsl); - si->si_ofs.mdata_ofs = merge_bytes(si->si_data.mdata_ofsh, - si->si_data.mdata_ofsl); - return rc; -} - -static int cyttsp4_si_get_cydata(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int read_offset; - int mfgid_sz, calc_mfgid_sz; - void *p; - int rc; - - if (si->si_ofs.test_ofs <= si->si_ofs.cydata_ofs) { - dev_err(cd->dev, - "%s: invalid offset test_ofs: %zu, cydata_ofs: %zu\n", - __func__, si->si_ofs.test_ofs, si->si_ofs.cydata_ofs); - return -EINVAL; - } - - si->si_ofs.cydata_size = si->si_ofs.test_ofs - si->si_ofs.cydata_ofs; - dev_dbg(cd->dev, "%s: cydata size: %zd\n", __func__, - si->si_ofs.cydata_size); - - p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate cydata memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.cydata = p; - - read_offset = si->si_ofs.cydata_ofs; - - /* Read the CYDA registers up to MFGID field */ - rc = cyttsp4_adap_read(cd, read_offset, - offsetof(struct cyttsp4_cydata, mfgid_sz) - + sizeof(si->si_ptrs.cydata->mfgid_sz), - si->si_ptrs.cydata); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read cydata r=%d\n", - __func__, rc); - return rc; - } - - /* Check MFGID size */ - mfgid_sz = si->si_ptrs.cydata->mfgid_sz; - calc_mfgid_sz = si->si_ofs.cydata_size - sizeof(struct cyttsp4_cydata); - if (mfgid_sz != calc_mfgid_sz) { - dev_err(cd->dev, "%s: mismatch in MFGID size, reported:%d calculated:%d\n", - __func__, mfgid_sz, calc_mfgid_sz); - return -EINVAL; - } - - read_offset += offsetof(struct cyttsp4_cydata, mfgid_sz) - + sizeof(si->si_ptrs.cydata->mfgid_sz); - - /* Read the CYDA registers for MFGID field */ - rc = cyttsp4_adap_read(cd, read_offset, si->si_ptrs.cydata->mfgid_sz, - si->si_ptrs.cydata->mfg_id); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read cydata r=%d\n", - __func__, rc); - return rc; - } - - read_offset += si->si_ptrs.cydata->mfgid_sz; - - /* Read the rest of the CYDA registers */ - rc = cyttsp4_adap_read(cd, read_offset, - sizeof(struct cyttsp4_cydata) - - offsetof(struct cyttsp4_cydata, cyito_idh), - &si->si_ptrs.cydata->cyito_idh); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read cydata r=%d\n", - __func__, rc); - return rc; - } - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.cydata, - si->si_ofs.cydata_size, "sysinfo_cydata"); - return rc; -} - -static int cyttsp4_si_get_test_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - if (si->si_ofs.pcfg_ofs <= si->si_ofs.test_ofs) { - dev_err(cd->dev, - "%s: invalid offset pcfg_ofs: %zu, test_ofs: %zu\n", - __func__, si->si_ofs.pcfg_ofs, si->si_ofs.test_ofs); - return -EINVAL; - } - - si->si_ofs.test_size = si->si_ofs.pcfg_ofs - si->si_ofs.test_ofs; - - p = krealloc(si->si_ptrs.test, si->si_ofs.test_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate test memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.test = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.test_ofs, si->si_ofs.test_size, - si->si_ptrs.test); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read test data r=%d\n", - __func__, rc); - return rc; - } - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.test, si->si_ofs.test_size, - "sysinfo_test_data"); - if (si->si_ptrs.test->post_codel & - CY_POST_CODEL_WDG_RST) - dev_info(cd->dev, "%s: %s codel=%02X\n", - __func__, "Reset was a WATCHDOG RESET", - si->si_ptrs.test->post_codel); - - if (!(si->si_ptrs.test->post_codel & - CY_POST_CODEL_CFG_DATA_CRC_FAIL)) - dev_info(cd->dev, "%s: %s codel=%02X\n", __func__, - "Config Data CRC FAIL", - si->si_ptrs.test->post_codel); - - if (!(si->si_ptrs.test->post_codel & - CY_POST_CODEL_PANEL_TEST_FAIL)) - dev_info(cd->dev, "%s: %s codel=%02X\n", - __func__, "PANEL TEST FAIL", - si->si_ptrs.test->post_codel); - - dev_info(cd->dev, "%s: SCANNING is %s codel=%02X\n", - __func__, si->si_ptrs.test->post_codel & 0x08 ? - "ENABLED" : "DISABLED", - si->si_ptrs.test->post_codel); - return rc; -} - -static int cyttsp4_si_get_pcfg_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - if (si->si_ofs.opcfg_ofs <= si->si_ofs.pcfg_ofs) { - dev_err(cd->dev, - "%s: invalid offset opcfg_ofs: %zu, pcfg_ofs: %zu\n", - __func__, si->si_ofs.opcfg_ofs, si->si_ofs.pcfg_ofs); - return -EINVAL; - } - - si->si_ofs.pcfg_size = si->si_ofs.opcfg_ofs - si->si_ofs.pcfg_ofs; - - p = krealloc(si->si_ptrs.pcfg, si->si_ofs.pcfg_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate pcfg memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.pcfg = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.pcfg_ofs, si->si_ofs.pcfg_size, - si->si_ptrs.pcfg); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read pcfg data r=%d\n", - __func__, rc); - return rc; - } - - si->si_ofs.max_x = merge_bytes((si->si_ptrs.pcfg->res_xh - & CY_PCFG_RESOLUTION_X_MASK), si->si_ptrs.pcfg->res_xl); - si->si_ofs.x_origin = !!(si->si_ptrs.pcfg->res_xh - & CY_PCFG_ORIGIN_X_MASK); - si->si_ofs.max_y = merge_bytes((si->si_ptrs.pcfg->res_yh - & CY_PCFG_RESOLUTION_Y_MASK), si->si_ptrs.pcfg->res_yl); - si->si_ofs.y_origin = !!(si->si_ptrs.pcfg->res_yh - & CY_PCFG_ORIGIN_Y_MASK); - si->si_ofs.max_p = merge_bytes(si->si_ptrs.pcfg->max_zh, - si->si_ptrs.pcfg->max_zl); - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.pcfg, - si->si_ofs.pcfg_size, "sysinfo_pcfg_data"); - return rc; -} - -static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - struct cyttsp4_tch_abs_params *tch; - struct cyttsp4_tch_rec_params *tch_old, *tch_new; - enum cyttsp4_tch_abs abs; - int i; - void *p; - int rc; - - if (si->si_ofs.ddata_ofs <= si->si_ofs.opcfg_ofs) { - dev_err(cd->dev, - "%s: invalid offset ddata_ofs: %zu, opcfg_ofs: %zu\n", - __func__, si->si_ofs.ddata_ofs, si->si_ofs.opcfg_ofs); - return -EINVAL; - } - - si->si_ofs.opcfg_size = si->si_ofs.ddata_ofs - si->si_ofs.opcfg_ofs; - - p = krealloc(si->si_ptrs.opcfg, si->si_ofs.opcfg_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate opcfg memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.opcfg = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.opcfg_ofs, si->si_ofs.opcfg_size, - si->si_ptrs.opcfg); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read opcfg data r=%d\n", - __func__, rc); - return rc; - } - si->si_ofs.cmd_ofs = si->si_ptrs.opcfg->cmd_ofs; - si->si_ofs.rep_ofs = si->si_ptrs.opcfg->rep_ofs; - si->si_ofs.rep_sz = (si->si_ptrs.opcfg->rep_szh * 256) + - si->si_ptrs.opcfg->rep_szl; - si->si_ofs.num_btns = si->si_ptrs.opcfg->num_btns; - si->si_ofs.num_btn_regs = (si->si_ofs.num_btns + - CY_NUM_BTN_PER_REG - 1) / CY_NUM_BTN_PER_REG; - si->si_ofs.tt_stat_ofs = si->si_ptrs.opcfg->tt_stat_ofs; - si->si_ofs.obj_cfg0 = si->si_ptrs.opcfg->obj_cfg0; - si->si_ofs.max_tchs = si->si_ptrs.opcfg->max_tchs & - CY_BYTE_OFS_MASK; - si->si_ofs.tch_rec_size = si->si_ptrs.opcfg->tch_rec_size & - CY_BYTE_OFS_MASK; - - /* Get the old touch fields */ - for (abs = CY_TCH_X; abs < CY_NUM_TCH_FIELDS; abs++) { - tch = &si->si_ofs.tch_abs[abs]; - tch_old = &si->si_ptrs.opcfg->tch_rec_old[abs]; - - tch->ofs = tch_old->loc & CY_BYTE_OFS_MASK; - tch->size = cyttsp4_bits_2_bytes(tch_old->size, - &tch->max); - tch->bofs = (tch_old->loc & CY_BOFS_MASK) >> CY_BOFS_SHIFT; - } - - /* button fields */ - si->si_ofs.btn_rec_size = si->si_ptrs.opcfg->btn_rec_size; - si->si_ofs.btn_diff_ofs = si->si_ptrs.opcfg->btn_diff_ofs; - si->si_ofs.btn_diff_size = si->si_ptrs.opcfg->btn_diff_size; - - if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) { - /* Get the extended touch fields */ - for (i = 0; i < CY_NUM_EXT_TCH_FIELDS; abs++, i++) { - tch = &si->si_ofs.tch_abs[abs]; - tch_new = &si->si_ptrs.opcfg->tch_rec_new[i]; - - tch->ofs = tch_new->loc & CY_BYTE_OFS_MASK; - tch->size = cyttsp4_bits_2_bytes(tch_new->size, - &tch->max); - tch->bofs = (tch_new->loc & CY_BOFS_MASK) >> CY_BOFS_SHIFT; - } - } - - for (abs = 0; abs < CY_TCH_NUM_ABS; abs++) { - dev_dbg(cd->dev, "%s: tch_rec_%s\n", __func__, - cyttsp4_tch_abs_string[abs]); - dev_dbg(cd->dev, "%s: ofs =%2zd\n", __func__, - si->si_ofs.tch_abs[abs].ofs); - dev_dbg(cd->dev, "%s: siz =%2zd\n", __func__, - si->si_ofs.tch_abs[abs].size); - dev_dbg(cd->dev, "%s: max =%2zd\n", __func__, - si->si_ofs.tch_abs[abs].max); - dev_dbg(cd->dev, "%s: bofs=%2zd\n", __func__, - si->si_ofs.tch_abs[abs].bofs); - } - - si->si_ofs.mode_size = si->si_ofs.tt_stat_ofs + 1; - si->si_ofs.data_size = si->si_ofs.max_tchs * - si->si_ptrs.opcfg->tch_rec_size; - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.opcfg, - si->si_ofs.opcfg_size, "sysinfo_opcfg_data"); - - return 0; -} - -static int cyttsp4_si_get_ddata(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - si->si_ofs.ddata_size = si->si_ofs.mdata_ofs - si->si_ofs.ddata_ofs; - - p = krealloc(si->si_ptrs.ddata, si->si_ofs.ddata_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: fail alloc ddata memory\n", __func__); - return -ENOMEM; - } - si->si_ptrs.ddata = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.ddata_ofs, si->si_ofs.ddata_size, - si->si_ptrs.ddata); - if (rc < 0) - dev_err(cd->dev, "%s: fail read ddata data r=%d\n", - __func__, rc); - else - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.ddata, - si->si_ofs.ddata_size, "sysinfo_ddata"); - return rc; -} - -static int cyttsp4_si_get_mdata(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - si->si_ofs.mdata_size = si->si_ofs.map_sz - si->si_ofs.mdata_ofs; - - p = krealloc(si->si_ptrs.mdata, si->si_ofs.mdata_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: fail alloc mdata memory\n", __func__); - return -ENOMEM; - } - si->si_ptrs.mdata = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.mdata_ofs, si->si_ofs.mdata_size, - si->si_ptrs.mdata); - if (rc < 0) - dev_err(cd->dev, "%s: fail read mdata data r=%d\n", - __func__, rc); - else - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.mdata, - si->si_ofs.mdata_size, "sysinfo_mdata"); - return rc; -} - -static int cyttsp4_si_get_btn_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int btn; - int num_defined_keys; - u16 *key_table; - void *p; - int rc = 0; - - if (si->si_ofs.num_btns) { - si->si_ofs.btn_keys_size = si->si_ofs.num_btns * - sizeof(struct cyttsp4_btn); - - p = krealloc(si->btn, si->si_ofs.btn_keys_size, - GFP_KERNEL|__GFP_ZERO); - if (p == NULL) { - dev_err(cd->dev, "%s: %s\n", __func__, - "fail alloc btn_keys memory"); - return -ENOMEM; - } - si->btn = p; - - if (cd->cpdata->sett[CY_IC_GRPNUM_BTN_KEYS] == NULL) - num_defined_keys = 0; - else if (cd->cpdata->sett[CY_IC_GRPNUM_BTN_KEYS]->data == NULL) - num_defined_keys = 0; - else - num_defined_keys = cd->cpdata->sett - [CY_IC_GRPNUM_BTN_KEYS]->size; - - for (btn = 0; btn < si->si_ofs.num_btns && - btn < num_defined_keys; btn++) { - key_table = (u16 *)cd->cpdata->sett - [CY_IC_GRPNUM_BTN_KEYS]->data; - si->btn[btn].key_code = key_table[btn]; - si->btn[btn].state = CY_BTN_RELEASED; - si->btn[btn].enabled = true; - } - for (; btn < si->si_ofs.num_btns; btn++) { - si->btn[btn].key_code = KEY_RESERVED; - si->btn[btn].state = CY_BTN_RELEASED; - si->btn[btn].enabled = true; - } - - return rc; - } - - si->si_ofs.btn_keys_size = 0; - kfree(si->btn); - si->btn = NULL; - return rc; -} - -static int cyttsp4_si_get_op_data_ptrs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - - p = krealloc(si->xy_mode, si->si_ofs.mode_size, GFP_KERNEL|__GFP_ZERO); - if (p == NULL) - return -ENOMEM; - si->xy_mode = p; - - p = krealloc(si->xy_data, si->si_ofs.data_size, GFP_KERNEL|__GFP_ZERO); - if (p == NULL) - return -ENOMEM; - si->xy_data = p; - - p = krealloc(si->btn_rec_data, - si->si_ofs.btn_rec_size * si->si_ofs.num_btns, - GFP_KERNEL|__GFP_ZERO); - if (p == NULL) - return -ENOMEM; - si->btn_rec_data = p; - - return 0; -} - -static void cyttsp4_si_put_log_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - dev_dbg(cd->dev, "%s: cydata_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.cydata_ofs, si->si_ofs.cydata_size); - dev_dbg(cd->dev, "%s: test_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.test_ofs, si->si_ofs.test_size); - dev_dbg(cd->dev, "%s: pcfg_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.pcfg_ofs, si->si_ofs.pcfg_size); - dev_dbg(cd->dev, "%s: opcfg_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.opcfg_ofs, si->si_ofs.opcfg_size); - dev_dbg(cd->dev, "%s: ddata_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.ddata_ofs, si->si_ofs.ddata_size); - dev_dbg(cd->dev, "%s: mdata_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.mdata_ofs, si->si_ofs.mdata_size); - - dev_dbg(cd->dev, "%s: cmd_ofs =%4zd\n", __func__, - si->si_ofs.cmd_ofs); - dev_dbg(cd->dev, "%s: rep_ofs =%4zd\n", __func__, - si->si_ofs.rep_ofs); - dev_dbg(cd->dev, "%s: rep_sz =%4zd\n", __func__, - si->si_ofs.rep_sz); - dev_dbg(cd->dev, "%s: num_btns =%4zd\n", __func__, - si->si_ofs.num_btns); - dev_dbg(cd->dev, "%s: num_btn_regs =%4zd\n", __func__, - si->si_ofs.num_btn_regs); - dev_dbg(cd->dev, "%s: tt_stat_ofs =%4zd\n", __func__, - si->si_ofs.tt_stat_ofs); - dev_dbg(cd->dev, "%s: tch_rec_size =%4zd\n", __func__, - si->si_ofs.tch_rec_size); - dev_dbg(cd->dev, "%s: max_tchs =%4zd\n", __func__, - si->si_ofs.max_tchs); - dev_dbg(cd->dev, "%s: mode_size =%4zd\n", __func__, - si->si_ofs.mode_size); - dev_dbg(cd->dev, "%s: data_size =%4zd\n", __func__, - si->si_ofs.data_size); - dev_dbg(cd->dev, "%s: map_sz =%4zd\n", __func__, - si->si_ofs.map_sz); - - dev_dbg(cd->dev, "%s: btn_rec_size =%2zd\n", __func__, - si->si_ofs.btn_rec_size); - dev_dbg(cd->dev, "%s: btn_diff_ofs =%2zd\n", __func__, - si->si_ofs.btn_diff_ofs); - dev_dbg(cd->dev, "%s: btn_diff_size =%2zd\n", __func__, - si->si_ofs.btn_diff_size); - - dev_dbg(cd->dev, "%s: max_x = 0x%04zX (%zd)\n", __func__, - si->si_ofs.max_x, si->si_ofs.max_x); - dev_dbg(cd->dev, "%s: x_origin = %zd (%s)\n", __func__, - si->si_ofs.x_origin, - si->si_ofs.x_origin == CY_NORMAL_ORIGIN ? - "left corner" : "right corner"); - dev_dbg(cd->dev, "%s: max_y = 0x%04zX (%zd)\n", __func__, - si->si_ofs.max_y, si->si_ofs.max_y); - dev_dbg(cd->dev, "%s: y_origin = %zd (%s)\n", __func__, - si->si_ofs.y_origin, - si->si_ofs.y_origin == CY_NORMAL_ORIGIN ? - "upper corner" : "lower corner"); - dev_dbg(cd->dev, "%s: max_p = 0x%04zX (%zd)\n", __func__, - si->si_ofs.max_p, si->si_ofs.max_p); - - dev_dbg(cd->dev, "%s: xy_mode=%p xy_data=%p\n", __func__, - si->xy_mode, si->xy_data); -} - -static int cyttsp4_get_sysinfo_regs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int rc; - - rc = cyttsp4_si_data_offsets(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_cydata(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_test_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_pcfg_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_opcfg_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_ddata(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_mdata(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_btn_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_op_data_ptrs(cd); - if (rc < 0) { - dev_err(cd->dev, "%s: failed to get_op_data\n", - __func__); - return rc; - } - - cyttsp4_si_put_log_data(cd); - - /* provide flow control handshake */ - rc = cyttsp4_handshake(cd, si->si_data.hst_mode); - if (rc < 0) - dev_err(cd->dev, "%s: handshake fail on sysinfo reg\n", - __func__); - - si->ready = true; - return rc; -} - -static void cyttsp4_queue_startup_(struct cyttsp4 *cd) -{ - if (cd->startup_state == STARTUP_NONE) { - cd->startup_state = STARTUP_QUEUED; - schedule_work(&cd->startup_work); - dev_dbg(cd->dev, "%s: cyttsp4_startup queued\n", __func__); - } else { - dev_dbg(cd->dev, "%s: startup_state = %d\n", __func__, - cd->startup_state); - } -} - -static void cyttsp4_report_slot_liftoff(struct cyttsp4_mt_data *md, - int max_slots) -{ - int t; - - if (md->num_prv_tch == 0) - return; - - for (t = 0; t < max_slots; t++) { - input_mt_slot(md->input, t); - input_mt_report_slot_inactive(md->input); - } -} - -static void cyttsp4_lift_all(struct cyttsp4_mt_data *md) -{ - if (!md->si) - return; - - if (md->num_prv_tch != 0) { - cyttsp4_report_slot_liftoff(md, - md->si->si_ofs.tch_abs[CY_TCH_T].max); - input_sync(md->input); - md->num_prv_tch = 0; - } -} - -static void cyttsp4_get_touch_axis(struct cyttsp4_mt_data *md, - int *axis, int size, int max, u8 *xy_data, int bofs) -{ - int nbyte; - int next; - - for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) { - dev_vdbg(&md->input->dev, - "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p" - " xy_data[%d]=%02X(%d) bofs=%d\n", - __func__, *axis, *axis, size, max, xy_data, next, - xy_data[next], xy_data[next], bofs); - *axis = (*axis * 256) + (xy_data[next] >> bofs); - next++; - } - - *axis &= max - 1; - - dev_vdbg(&md->input->dev, - "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p" - " xy_data[%d]=%02X(%d)\n", - __func__, *axis, *axis, size, max, xy_data, next, - xy_data[next], xy_data[next]); -} - -static void cyttsp4_get_touch(struct cyttsp4_mt_data *md, - struct cyttsp4_touch *touch, u8 *xy_data) -{ - struct device *dev = &md->input->dev; - struct cyttsp4_sysinfo *si = md->si; - enum cyttsp4_tch_abs abs; - bool flipped; - - for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) { - cyttsp4_get_touch_axis(md, &touch->abs[abs], - si->si_ofs.tch_abs[abs].size, - si->si_ofs.tch_abs[abs].max, - xy_data + si->si_ofs.tch_abs[abs].ofs, - si->si_ofs.tch_abs[abs].bofs); - dev_vdbg(dev, "%s: get %s=%04X(%d)\n", __func__, - cyttsp4_tch_abs_string[abs], - touch->abs[abs], touch->abs[abs]); - } - - if (md->pdata->flags & CY_FLAG_FLIP) { - swap(touch->abs[CY_TCH_X], touch->abs[CY_TCH_Y]); - flipped = true; - } else - flipped = false; - - if (md->pdata->flags & CY_FLAG_INV_X) { - if (flipped) - touch->abs[CY_TCH_X] = md->si->si_ofs.max_y - - touch->abs[CY_TCH_X]; - else - touch->abs[CY_TCH_X] = md->si->si_ofs.max_x - - touch->abs[CY_TCH_X]; - } - if (md->pdata->flags & CY_FLAG_INV_Y) { - if (flipped) - touch->abs[CY_TCH_Y] = md->si->si_ofs.max_x - - touch->abs[CY_TCH_Y]; - else - touch->abs[CY_TCH_Y] = md->si->si_ofs.max_y - - touch->abs[CY_TCH_Y]; - } - - dev_vdbg(dev, "%s: flip=%s inv-x=%s inv-y=%s x=%04X(%d) y=%04X(%d)\n", - __func__, flipped ? "true" : "false", - md->pdata->flags & CY_FLAG_INV_X ? "true" : "false", - md->pdata->flags & CY_FLAG_INV_Y ? "true" : "false", - touch->abs[CY_TCH_X], touch->abs[CY_TCH_X], - touch->abs[CY_TCH_Y], touch->abs[CY_TCH_Y]); -} - -static void cyttsp4_final_sync(struct input_dev *input, int max_slots, int *ids) -{ - int t; - - for (t = 0; t < max_slots; t++) { - if (ids[t]) - continue; - input_mt_slot(input, t); - input_mt_report_slot_inactive(input); - } - - input_sync(input); -} - -static void cyttsp4_get_mt_touches(struct cyttsp4_mt_data *md, int num_cur_tch) -{ - struct device *dev = &md->input->dev; - struct cyttsp4_sysinfo *si = md->si; - struct cyttsp4_touch tch; - int sig; - int i, j, t = 0; - int ids[max(CY_TMA1036_MAX_TCH, CY_TMA4XX_MAX_TCH)]; - - memset(ids, 0, si->si_ofs.tch_abs[CY_TCH_T].max * sizeof(int)); - for (i = 0; i < num_cur_tch; i++) { - cyttsp4_get_touch(md, &tch, si->xy_data + - (i * si->si_ofs.tch_rec_size)); - if ((tch.abs[CY_TCH_T] < md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]) || - (tch.abs[CY_TCH_T] > md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MAX_OST])) { - dev_err(dev, "%s: tch=%d -> bad trk_id=%d max_id=%d\n", - __func__, i, tch.abs[CY_TCH_T], - md->pdata->frmwrk->abs[(CY_ABS_ID_OST * - CY_NUM_ABS_SET) + CY_MAX_OST]); - continue; - } - - /* use 0 based track id's */ - sig = md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + 0]; - if (sig != CY_IGNORE_VALUE) { - t = tch.abs[CY_TCH_T] - md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]; - if (tch.abs[CY_TCH_E] == CY_EV_LIFTOFF) { - dev_dbg(dev, "%s: t=%d e=%d lift-off\n", - __func__, t, tch.abs[CY_TCH_E]); - goto cyttsp4_get_mt_touches_pr_tch; - } - input_mt_slot(md->input, t); - input_mt_report_slot_state(md->input, MT_TOOL_FINGER, - true); - ids[t] = true; - } - - /* all devices: position and pressure fields */ - for (j = 0; j <= CY_ABS_W_OST; j++) { - sig = md->pdata->frmwrk->abs[((CY_ABS_X_OST + j) * - CY_NUM_ABS_SET) + 0]; - if (sig != CY_IGNORE_VALUE) - input_report_abs(md->input, sig, - tch.abs[CY_TCH_X + j]); - } - if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) { - /* - * TMA400 size and orientation fields: - * if pressure is non-zero and major touch - * signal is zero, then set major and minor touch - * signals to minimum non-zero value - */ - if (tch.abs[CY_TCH_P] > 0 && tch.abs[CY_TCH_MAJ] == 0) - tch.abs[CY_TCH_MAJ] = tch.abs[CY_TCH_MIN] = 1; - - /* Get the extended touch fields */ - for (j = 0; j < CY_NUM_EXT_TCH_FIELDS; j++) { - sig = md->pdata->frmwrk->abs - [((CY_ABS_MAJ_OST + j) * - CY_NUM_ABS_SET) + 0]; - if (sig != CY_IGNORE_VALUE) - input_report_abs(md->input, sig, - tch.abs[CY_TCH_MAJ + j]); - } - } - -cyttsp4_get_mt_touches_pr_tch: - if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) - dev_dbg(dev, - "%s: t=%d x=%d y=%d z=%d M=%d m=%d o=%d e=%d\n", - __func__, t, - tch.abs[CY_TCH_X], - tch.abs[CY_TCH_Y], - tch.abs[CY_TCH_P], - tch.abs[CY_TCH_MAJ], - tch.abs[CY_TCH_MIN], - tch.abs[CY_TCH_OR], - tch.abs[CY_TCH_E]); - else - dev_dbg(dev, - "%s: t=%d x=%d y=%d z=%d e=%d\n", __func__, - t, - tch.abs[CY_TCH_X], - tch.abs[CY_TCH_Y], - tch.abs[CY_TCH_P], - tch.abs[CY_TCH_E]); - } - - cyttsp4_final_sync(md->input, si->si_ofs.tch_abs[CY_TCH_T].max, ids); - - md->num_prv_tch = num_cur_tch; - - return; -} - -/* read xy_data for all current touches */ -static int cyttsp4_xy_worker(struct cyttsp4 *cd) -{ - struct cyttsp4_mt_data *md = &cd->md; - struct device *dev = &md->input->dev; - struct cyttsp4_sysinfo *si = md->si; - u8 num_cur_tch; - u8 hst_mode; - u8 rep_len; - u8 rep_stat; - u8 tt_stat; - int rc = 0; - - /* - * Get event data from cyttsp4 device. - * The event data includes all data - * for all active touches. - * Event data also includes button data - */ - /* - * Use 2 reads: - * 1st read to get mode + button bytes + touch count (core) - * 2nd read (optional) to get touch 1 - touch n data - */ - hst_mode = si->xy_mode[CY_REG_BASE]; - rep_len = si->xy_mode[si->si_ofs.rep_ofs]; - rep_stat = si->xy_mode[si->si_ofs.rep_ofs + 1]; - tt_stat = si->xy_mode[si->si_ofs.tt_stat_ofs]; - dev_vdbg(dev, "%s: %s%02X %s%d %s%02X %s%02X\n", __func__, - "hst_mode=", hst_mode, "rep_len=", rep_len, - "rep_stat=", rep_stat, "tt_stat=", tt_stat); - - num_cur_tch = GET_NUM_TOUCHES(tt_stat); - dev_vdbg(dev, "%s: num_cur_tch=%d\n", __func__, num_cur_tch); - - if (rep_len == 0 && num_cur_tch > 0) { - dev_err(dev, "%s: report length error rep_len=%d num_tch=%d\n", - __func__, rep_len, num_cur_tch); - goto cyttsp4_xy_worker_exit; - } - - /* read touches */ - if (num_cur_tch > 0) { - rc = cyttsp4_adap_read(cd, si->si_ofs.tt_stat_ofs + 1, - num_cur_tch * si->si_ofs.tch_rec_size, - si->xy_data); - if (rc < 0) { - dev_err(dev, "%s: read fail on touch regs r=%d\n", - __func__, rc); - goto cyttsp4_xy_worker_exit; - } - } - - /* print xy data */ - cyttsp4_pr_buf(dev, cd->pr_buf, si->xy_data, num_cur_tch * - si->si_ofs.tch_rec_size, "xy_data"); - - /* check any error conditions */ - if (IS_BAD_PKT(rep_stat)) { - dev_dbg(dev, "%s: Invalid buffer detected\n", __func__); - rc = 0; - goto cyttsp4_xy_worker_exit; - } - - if (IS_LARGE_AREA(tt_stat)) - dev_dbg(dev, "%s: Large area detected\n", __func__); - - if (num_cur_tch > si->si_ofs.max_tchs) { - dev_err(dev, "%s: too many tch; set to max tch (n=%d c=%zd)\n", - __func__, num_cur_tch, si->si_ofs.max_tchs); - num_cur_tch = si->si_ofs.max_tchs; - } - - /* extract xy_data for all currently reported touches */ - dev_vdbg(dev, "%s: extract data num_cur_tch=%d\n", __func__, - num_cur_tch); - if (num_cur_tch) - cyttsp4_get_mt_touches(md, num_cur_tch); - else - cyttsp4_lift_all(md); - - rc = 0; - -cyttsp4_xy_worker_exit: - return rc; -} - -static int cyttsp4_mt_attention(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - struct cyttsp4_mt_data *md = &cd->md; - int rc = 0; - - if (!md->si) - return 0; - - mutex_lock(&md->report_lock); - if (!md->is_suspended) { - /* core handles handshake */ - rc = cyttsp4_xy_worker(cd); - } else { - dev_vdbg(dev, "%s: Ignoring report while suspended\n", - __func__); - } - mutex_unlock(&md->report_lock); - if (rc < 0) - dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc); - - return rc; -} - -static irqreturn_t cyttsp4_irq(int irq, void *handle) -{ - struct cyttsp4 *cd = handle; - struct device *dev = cd->dev; - enum cyttsp4_mode cur_mode; - u8 cmd_ofs = cd->sysinfo.si_ofs.cmd_ofs; - u8 mode[3]; - int rc; - - /* - * Check whether this IRQ should be ignored (external) - * This should be the very first thing to check since - * ignore_irq may be set for a very short period of time - */ - if (atomic_read(&cd->ignore_irq)) { - dev_vdbg(dev, "%s: Ignoring IRQ\n", __func__); - return IRQ_HANDLED; - } - - dev_dbg(dev, "%s int:0x%x\n", __func__, cd->int_status); - - mutex_lock(&cd->system_lock); - - /* Just to debug */ - if (cd->sleep_state == SS_SLEEP_ON || cd->sleep_state == SS_SLEEPING) - dev_vdbg(dev, "%s: Received IRQ while in sleep\n", __func__); - - rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), mode); - if (rc) { - dev_err(cd->dev, "%s: Fail read adapter r=%d\n", __func__, rc); - goto cyttsp4_irq_exit; - } - dev_vdbg(dev, "%s mode[0-2]:0x%X 0x%X 0x%X\n", __func__, - mode[0], mode[1], mode[2]); - - if (IS_BOOTLOADER(mode[0], mode[1])) { - cur_mode = CY_MODE_BOOTLOADER; - dev_vdbg(dev, "%s: bl running\n", __func__); - if (cd->mode == CY_MODE_BOOTLOADER) { - /* Signal bootloader heartbeat heard */ - wake_up(&cd->wait_q); - goto cyttsp4_irq_exit; - } - - /* switch to bootloader */ - dev_dbg(dev, "%s: restart switch to bl m=%d -> m=%d\n", - __func__, cd->mode, cur_mode); - - /* catch operation->bl glitch */ - if (cd->mode != CY_MODE_UNKNOWN) { - /* Incase startup_state do not let startup_() */ - cd->mode = CY_MODE_UNKNOWN; - cyttsp4_queue_startup_(cd); - goto cyttsp4_irq_exit; - } - - /* - * do not wake thread on this switch since - * it is possible to get an early heartbeat - * prior to performing the reset - */ - cd->mode = cur_mode; - - goto cyttsp4_irq_exit; - } - - switch (mode[0] & CY_HST_MODE) { - case CY_HST_OPERATE: - cur_mode = CY_MODE_OPERATIONAL; - dev_vdbg(dev, "%s: operational\n", __func__); - break; - case CY_HST_CAT: - cur_mode = CY_MODE_CAT; - dev_vdbg(dev, "%s: CaT\n", __func__); - break; - case CY_HST_SYSINFO: - cur_mode = CY_MODE_SYSINFO; - dev_vdbg(dev, "%s: sysinfo\n", __func__); - break; - default: - cur_mode = CY_MODE_UNKNOWN; - dev_err(dev, "%s: unknown HST mode 0x%02X\n", __func__, - mode[0]); - break; - } - - /* Check whether this IRQ should be ignored (internal) */ - if (cd->int_status & CY_INT_IGNORE) { - dev_vdbg(dev, "%s: Ignoring IRQ\n", __func__); - goto cyttsp4_irq_exit; - } - - /* Check for wake up interrupt */ - if (cd->int_status & CY_INT_AWAKE) { - cd->int_status &= ~CY_INT_AWAKE; - wake_up(&cd->wait_q); - dev_vdbg(dev, "%s: Received wake up interrupt\n", __func__); - goto cyttsp4_irq_handshake; - } - - /* Expecting mode change interrupt */ - if ((cd->int_status & CY_INT_MODE_CHANGE) - && (mode[0] & CY_HST_MODE_CHANGE) == 0) { - cd->int_status &= ~CY_INT_MODE_CHANGE; - dev_dbg(dev, "%s: finish mode switch m=%d -> m=%d\n", - __func__, cd->mode, cur_mode); - cd->mode = cur_mode; - wake_up(&cd->wait_q); - goto cyttsp4_irq_handshake; - } - - /* compare current core mode to current device mode */ - dev_vdbg(dev, "%s: cd->mode=%d cur_mode=%d\n", - __func__, cd->mode, cur_mode); - if ((mode[0] & CY_HST_MODE_CHANGE) == 0 && cd->mode != cur_mode) { - /* Unexpected mode change occurred */ - dev_err(dev, "%s %d->%d 0x%x\n", __func__, cd->mode, - cur_mode, cd->int_status); - dev_dbg(dev, "%s: Unexpected mode change, startup\n", - __func__); - cyttsp4_queue_startup_(cd); - goto cyttsp4_irq_exit; - } - - /* Expecting command complete interrupt */ - dev_vdbg(dev, "%s: command byte:0x%x\n", __func__, mode[cmd_ofs]); - if ((cd->int_status & CY_INT_EXEC_CMD) - && mode[cmd_ofs] & CY_CMD_COMPLETE) { - cd->int_status &= ~CY_INT_EXEC_CMD; - dev_vdbg(dev, "%s: Received command complete interrupt\n", - __func__); - wake_up(&cd->wait_q); - /* - * It is possible to receive a single interrupt for - * command complete and touch/button status report. - * Continue processing for a possible status report. - */ - } - - /* This should be status report, read status regs */ - if (cd->mode == CY_MODE_OPERATIONAL) { - dev_vdbg(dev, "%s: Read status registers\n", __func__); - rc = cyttsp4_load_status_regs(cd); - if (rc < 0) - dev_err(dev, "%s: fail read mode regs r=%d\n", - __func__, rc); - } - - cyttsp4_mt_attention(cd); - -cyttsp4_irq_handshake: - /* handshake the event */ - dev_vdbg(dev, "%s: Handshake mode=0x%02X r=%d\n", - __func__, mode[0], rc); - rc = cyttsp4_handshake(cd, mode[0]); - if (rc < 0) - dev_err(dev, "%s: Fail handshake mode=0x%02X r=%d\n", - __func__, mode[0], rc); - - /* - * a non-zero udelay period is required for using - * IRQF_TRIGGER_LOW in order to delay until the - * device completes isr deassert - */ - udelay(cd->cpdata->level_irq_udelay); - -cyttsp4_irq_exit: - mutex_unlock(&cd->system_lock); - return IRQ_HANDLED; -} - -static void cyttsp4_start_wd_timer(struct cyttsp4 *cd) -{ - if (!CY_WATCHDOG_TIMEOUT) - return; - - mod_timer(&cd->watchdog_timer, jiffies + - msecs_to_jiffies(CY_WATCHDOG_TIMEOUT)); -} - -static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd) -{ - if (!CY_WATCHDOG_TIMEOUT) - return; - - /* - * Ensure we wait until the watchdog timer - * running on a different CPU finishes - */ - timer_shutdown_sync(&cd->watchdog_timer); - cancel_work_sync(&cd->watchdog_work); -} - -static void cyttsp4_watchdog_timer(struct timer_list *t) -{ - struct cyttsp4 *cd = from_timer(cd, t, watchdog_timer); - - dev_vdbg(cd->dev, "%s: Watchdog timer triggered\n", __func__); - - schedule_work(&cd->watchdog_work); - - return; -} - -static int cyttsp4_request_exclusive(struct cyttsp4 *cd, void *ownptr, - int timeout_ms) -{ - int t = msecs_to_jiffies(timeout_ms); - bool with_timeout = (timeout_ms != 0); - - mutex_lock(&cd->system_lock); - if (!cd->exclusive_dev && cd->exclusive_waits == 0) { - cd->exclusive_dev = ownptr; - goto exit; - } - - cd->exclusive_waits++; -wait: - mutex_unlock(&cd->system_lock); - if (with_timeout) { - t = wait_event_timeout(cd->wait_q, !cd->exclusive_dev, t); - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: tmo waiting exclusive access\n", - __func__); - mutex_lock(&cd->system_lock); - cd->exclusive_waits--; - mutex_unlock(&cd->system_lock); - return -ETIME; - } - } else { - wait_event(cd->wait_q, !cd->exclusive_dev); - } - mutex_lock(&cd->system_lock); - if (cd->exclusive_dev) - goto wait; - cd->exclusive_dev = ownptr; - cd->exclusive_waits--; -exit: - mutex_unlock(&cd->system_lock); - - return 0; -} - -/* - * returns error if was not owned - */ -static int cyttsp4_release_exclusive(struct cyttsp4 *cd, void *ownptr) -{ - mutex_lock(&cd->system_lock); - if (cd->exclusive_dev != ownptr) { - mutex_unlock(&cd->system_lock); - return -EINVAL; - } - - dev_vdbg(cd->dev, "%s: exclusive_dev %p freed\n", - __func__, cd->exclusive_dev); - cd->exclusive_dev = NULL; - wake_up(&cd->wait_q); - mutex_unlock(&cd->system_lock); - return 0; -} - -static int cyttsp4_wait_bl_heartbeat(struct cyttsp4 *cd) -{ - long t; - int rc = 0; - - /* wait heartbeat */ - dev_vdbg(cd->dev, "%s: wait heartbeat...\n", __func__); - t = wait_event_timeout(cd->wait_q, cd->mode == CY_MODE_BOOTLOADER, - msecs_to_jiffies(CY_CORE_RESET_AND_WAIT_TIMEOUT)); - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: tmo waiting bl heartbeat cd->mode=%d\n", - __func__, cd->mode); - rc = -ETIME; - } - - return rc; -} - -static int cyttsp4_wait_sysinfo_mode(struct cyttsp4 *cd) -{ - long t; - - dev_vdbg(cd->dev, "%s: wait sysinfo...\n", __func__); - - t = wait_event_timeout(cd->wait_q, cd->mode == CY_MODE_SYSINFO, - msecs_to_jiffies(CY_CORE_MODE_CHANGE_TIMEOUT)); - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: tmo waiting exit bl cd->mode=%d\n", - __func__, cd->mode); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_MODE_CHANGE; - mutex_unlock(&cd->system_lock); - return -ETIME; - } - - return 0; -} - -static int cyttsp4_reset_and_wait(struct cyttsp4 *cd) -{ - int rc; - - /* reset hardware */ - mutex_lock(&cd->system_lock); - dev_dbg(cd->dev, "%s: reset hw...\n", __func__); - rc = cyttsp4_hw_reset(cd); - cd->mode = CY_MODE_UNKNOWN; - mutex_unlock(&cd->system_lock); - if (rc < 0) { - dev_err(cd->dev, "%s:Fail hw reset r=%d\n", __func__, rc); - return rc; - } - - return cyttsp4_wait_bl_heartbeat(cd); -} - -/* - * returns err if refused or timeout; block until mode change complete - * bit is set (mode change interrupt) - */ -static int cyttsp4_set_mode(struct cyttsp4 *cd, int new_mode) -{ - u8 new_dev_mode; - u8 mode; - long t; - int rc; - - switch (new_mode) { - case CY_MODE_OPERATIONAL: - new_dev_mode = CY_HST_OPERATE; - break; - case CY_MODE_SYSINFO: - new_dev_mode = CY_HST_SYSINFO; - break; - case CY_MODE_CAT: - new_dev_mode = CY_HST_CAT; - break; - default: - dev_err(cd->dev, "%s: invalid mode: %02X(%d)\n", - __func__, new_mode, new_mode); - return -EINVAL; - } - - /* change mode */ - dev_dbg(cd->dev, "%s: %s=%p new_dev_mode=%02X new_mode=%d\n", - __func__, "have exclusive", cd->exclusive_dev, - new_dev_mode, new_mode); - - mutex_lock(&cd->system_lock); - rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); - if (rc < 0) { - mutex_unlock(&cd->system_lock); - dev_err(cd->dev, "%s: Fail read mode r=%d\n", - __func__, rc); - goto exit; - } - - /* Clear device mode bits and set to new mode */ - mode &= ~CY_HST_MODE; - mode |= new_dev_mode | CY_HST_MODE_CHANGE; - - cd->int_status |= CY_INT_MODE_CHANGE; - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(mode), &mode); - mutex_unlock(&cd->system_lock); - if (rc < 0) { - dev_err(cd->dev, "%s: Fail write mode change r=%d\n", - __func__, rc); - goto exit; - } - - /* wait for mode change done interrupt */ - t = wait_event_timeout(cd->wait_q, - (cd->int_status & CY_INT_MODE_CHANGE) == 0, - msecs_to_jiffies(CY_CORE_MODE_CHANGE_TIMEOUT)); - dev_dbg(cd->dev, "%s: back from wait t=%ld cd->mode=%d\n", - __func__, t, cd->mode); - - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: %s\n", __func__, - "tmo waiting mode change"); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_MODE_CHANGE; - mutex_unlock(&cd->system_lock); - rc = -EINVAL; - } - -exit: - return rc; -} - -static void cyttsp4_watchdog_work(struct work_struct *work) -{ - struct cyttsp4 *cd = - container_of(work, struct cyttsp4, watchdog_work); - u8 *mode; - int retval; - - mutex_lock(&cd->system_lock); - retval = cyttsp4_load_status_regs(cd); - if (retval < 0) { - dev_err(cd->dev, - "%s: failed to access device in watchdog timer r=%d\n", - __func__, retval); - cyttsp4_queue_startup_(cd); - goto cyttsp4_timer_watchdog_exit_error; - } - mode = &cd->sysinfo.xy_mode[CY_REG_BASE]; - if (IS_BOOTLOADER(mode[0], mode[1])) { - dev_err(cd->dev, - "%s: device found in bootloader mode when operational mode\n", - __func__); - cyttsp4_queue_startup_(cd); - goto cyttsp4_timer_watchdog_exit_error; - } - - cyttsp4_start_wd_timer(cd); -cyttsp4_timer_watchdog_exit_error: - mutex_unlock(&cd->system_lock); - return; -} - -static int cyttsp4_core_sleep_(struct cyttsp4 *cd) -{ - enum cyttsp4_sleep_state ss = SS_SLEEP_ON; - enum cyttsp4_int_state int_status = CY_INT_IGNORE; - int rc = 0; - u8 mode[2]; - - /* Already in sleep mode? */ - mutex_lock(&cd->system_lock); - if (cd->sleep_state == SS_SLEEP_ON) { - mutex_unlock(&cd->system_lock); - return 0; - } - cd->sleep_state = SS_SLEEPING; - mutex_unlock(&cd->system_lock); - - cyttsp4_stop_wd_timer(cd); - - /* Wait until currently running IRQ handler exits and disable IRQ */ - disable_irq(cd->irq); - - dev_vdbg(cd->dev, "%s: write DEEP SLEEP...\n", __func__); - mutex_lock(&cd->system_lock); - rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); - if (rc) { - mutex_unlock(&cd->system_lock); - dev_err(cd->dev, "%s: Fail read adapter r=%d\n", __func__, rc); - goto error; - } - - if (IS_BOOTLOADER(mode[0], mode[1])) { - mutex_unlock(&cd->system_lock); - dev_err(cd->dev, "%s: Device in BOOTLOADER mode.\n", __func__); - rc = -EINVAL; - goto error; - } - - mode[0] |= CY_HST_SLEEP; - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(mode[0]), &mode[0]); - mutex_unlock(&cd->system_lock); - if (rc) { - dev_err(cd->dev, "%s: Fail write adapter r=%d\n", __func__, rc); - goto error; - } - dev_vdbg(cd->dev, "%s: write DEEP SLEEP succeeded\n", __func__); - - if (cd->cpdata->power) { - dev_dbg(cd->dev, "%s: Power down HW\n", __func__); - rc = cd->cpdata->power(cd->cpdata, 0, cd->dev, &cd->ignore_irq); - } else { - dev_dbg(cd->dev, "%s: No power function\n", __func__); - rc = 0; - } - if (rc < 0) { - dev_err(cd->dev, "%s: HW Power down fails r=%d\n", - __func__, rc); - goto error; - } - - /* Give time to FW to sleep */ - msleep(50); - - goto exit; - -error: - ss = SS_SLEEP_OFF; - int_status = CY_INT_NONE; - cyttsp4_start_wd_timer(cd); - -exit: - mutex_lock(&cd->system_lock); - cd->sleep_state = ss; - cd->int_status |= int_status; - mutex_unlock(&cd->system_lock); - enable_irq(cd->irq); - return rc; -} - -static int cyttsp4_startup_(struct cyttsp4 *cd) -{ - int retry = CY_CORE_STARTUP_RETRY_COUNT; - int rc; - - cyttsp4_stop_wd_timer(cd); - -reset: - if (retry != CY_CORE_STARTUP_RETRY_COUNT) - dev_dbg(cd->dev, "%s: Retry %d\n", __func__, - CY_CORE_STARTUP_RETRY_COUNT - retry); - - /* reset hardware and wait for heartbeat */ - rc = cyttsp4_reset_and_wait(cd); - if (rc < 0) { - dev_err(cd->dev, "%s: Error on h/w reset r=%d\n", __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - /* exit bl into sysinfo mode */ - dev_vdbg(cd->dev, "%s: write exit ldr...\n", __func__); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_IGNORE; - cd->int_status |= CY_INT_MODE_CHANGE; - - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(ldr_exit), - (u8 *)ldr_exit); - mutex_unlock(&cd->system_lock); - if (rc < 0) { - dev_err(cd->dev, "%s: Fail write r=%d\n", __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - rc = cyttsp4_wait_sysinfo_mode(cd); - if (rc < 0) { - u8 buf[sizeof(ldr_err_app)]; - int rc1; - - /* Check for invalid/corrupted touch application */ - rc1 = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(ldr_err_app), - buf); - if (rc1) { - dev_err(cd->dev, "%s: Fail read r=%d\n", __func__, rc1); - } else if (!memcmp(buf, ldr_err_app, sizeof(ldr_err_app))) { - dev_err(cd->dev, "%s: Error launching touch application\n", - __func__); - mutex_lock(&cd->system_lock); - cd->invalid_touch_app = true; - mutex_unlock(&cd->system_lock); - goto exit_no_wd; - } - - if (retry--) - goto reset; - goto exit; - } - - mutex_lock(&cd->system_lock); - cd->invalid_touch_app = false; - mutex_unlock(&cd->system_lock); - - /* read sysinfo data */ - dev_vdbg(cd->dev, "%s: get sysinfo regs..\n", __func__); - rc = cyttsp4_get_sysinfo_regs(cd); - if (rc < 0) { - dev_err(cd->dev, "%s: failed to get sysinfo regs rc=%d\n", - __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - rc = cyttsp4_set_mode(cd, CY_MODE_OPERATIONAL); - if (rc < 0) { - dev_err(cd->dev, "%s: failed to set mode to operational rc=%d\n", - __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - cyttsp4_lift_all(&cd->md); - - /* restore to sleep if was suspended */ - mutex_lock(&cd->system_lock); - if (cd->sleep_state == SS_SLEEP_ON) { - cd->sleep_state = SS_SLEEP_OFF; - mutex_unlock(&cd->system_lock); - cyttsp4_core_sleep_(cd); - goto exit_no_wd; - } - mutex_unlock(&cd->system_lock); - -exit: - cyttsp4_start_wd_timer(cd); -exit_no_wd: - return rc; -} - -static int cyttsp4_startup(struct cyttsp4 *cd) -{ - int rc; - - mutex_lock(&cd->system_lock); - cd->startup_state = STARTUP_RUNNING; - mutex_unlock(&cd->system_lock); - - rc = cyttsp4_request_exclusive(cd, cd->dev, - CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT); - if (rc < 0) { - dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", - __func__, cd->exclusive_dev, cd->dev); - goto exit; - } - - rc = cyttsp4_startup_(cd); - - if (cyttsp4_release_exclusive(cd, cd->dev) < 0) - /* Don't return fail code, mode is already changed. */ - dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); - else - dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); - -exit: - mutex_lock(&cd->system_lock); - cd->startup_state = STARTUP_NONE; - mutex_unlock(&cd->system_lock); - - /* Wake the waiters for end of startup */ - wake_up(&cd->wait_q); - - return rc; -} - -static void cyttsp4_startup_work_function(struct work_struct *work) -{ - struct cyttsp4 *cd = container_of(work, struct cyttsp4, startup_work); - int rc; - - rc = cyttsp4_startup(cd); - if (rc < 0) - dev_err(cd->dev, "%s: Fail queued startup r=%d\n", - __func__, rc); -} - -static void cyttsp4_free_si_ptrs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - - if (!si) - return; - - kfree(si->si_ptrs.cydata); - kfree(si->si_ptrs.test); - kfree(si->si_ptrs.pcfg); - kfree(si->si_ptrs.opcfg); - kfree(si->si_ptrs.ddata); - kfree(si->si_ptrs.mdata); - kfree(si->btn); - kfree(si->xy_mode); - kfree(si->xy_data); - kfree(si->btn_rec_data); -} - -static int cyttsp4_core_sleep(struct cyttsp4 *cd) -{ - int rc; - - rc = cyttsp4_request_exclusive(cd, cd->dev, - CY_CORE_SLEEP_REQUEST_EXCLUSIVE_TIMEOUT); - if (rc < 0) { - dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", - __func__, cd->exclusive_dev, cd->dev); - return 0; - } - - rc = cyttsp4_core_sleep_(cd); - - if (cyttsp4_release_exclusive(cd, cd->dev) < 0) - dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); - else - dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); - - return rc; -} - -static int cyttsp4_core_wake_(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - int rc; - u8 mode; - int t; - - /* Already woken? */ - mutex_lock(&cd->system_lock); - if (cd->sleep_state == SS_SLEEP_OFF) { - mutex_unlock(&cd->system_lock); - return 0; - } - cd->int_status &= ~CY_INT_IGNORE; - cd->int_status |= CY_INT_AWAKE; - cd->sleep_state = SS_WAKING; - - if (cd->cpdata->power) { - dev_dbg(dev, "%s: Power up HW\n", __func__); - rc = cd->cpdata->power(cd->cpdata, 1, dev, &cd->ignore_irq); - } else { - dev_dbg(dev, "%s: No power function\n", __func__); - rc = -ENOSYS; - } - if (rc < 0) { - dev_err(dev, "%s: HW Power up fails r=%d\n", - __func__, rc); - - /* Initiate a read transaction to wake up */ - cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); - } else - dev_vdbg(cd->dev, "%s: HW power up succeeds\n", - __func__); - mutex_unlock(&cd->system_lock); - - t = wait_event_timeout(cd->wait_q, - (cd->int_status & CY_INT_AWAKE) == 0, - msecs_to_jiffies(CY_CORE_WAKEUP_TIMEOUT)); - if (IS_TMO(t)) { - dev_err(dev, "%s: TMO waiting for wakeup\n", __func__); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_AWAKE; - /* Try starting up */ - cyttsp4_queue_startup_(cd); - mutex_unlock(&cd->system_lock); - } - - mutex_lock(&cd->system_lock); - cd->sleep_state = SS_SLEEP_OFF; - mutex_unlock(&cd->system_lock); - - cyttsp4_start_wd_timer(cd); - - return 0; -} - -static int cyttsp4_core_wake(struct cyttsp4 *cd) -{ - int rc; - - rc = cyttsp4_request_exclusive(cd, cd->dev, - CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT); - if (rc < 0) { - dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", - __func__, cd->exclusive_dev, cd->dev); - return 0; - } - - rc = cyttsp4_core_wake_(cd); - - if (cyttsp4_release_exclusive(cd, cd->dev) < 0) - dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); - else - dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); - - return rc; -} - -static int cyttsp4_core_suspend(struct device *dev) -{ - struct cyttsp4 *cd = dev_get_drvdata(dev); - struct cyttsp4_mt_data *md = &cd->md; - int rc; - - md->is_suspended = true; - - rc = cyttsp4_core_sleep(cd); - if (rc < 0) { - dev_err(dev, "%s: Error on sleep\n", __func__); - return -EAGAIN; - } - return 0; -} - -static int cyttsp4_core_resume(struct device *dev) -{ - struct cyttsp4 *cd = dev_get_drvdata(dev); - struct cyttsp4_mt_data *md = &cd->md; - int rc; - - md->is_suspended = false; - - rc = cyttsp4_core_wake(cd); - if (rc < 0) { - dev_err(dev, "%s: Error on wake\n", __func__); - return -EAGAIN; - } - - return 0; -} - -EXPORT_GPL_RUNTIME_DEV_PM_OPS(cyttsp4_pm_ops, - cyttsp4_core_suspend, cyttsp4_core_resume, NULL); - -static int cyttsp4_mt_open(struct input_dev *input) -{ - pm_runtime_get(input->dev.parent); - return 0; -} - -static void cyttsp4_mt_close(struct input_dev *input) -{ - struct cyttsp4_mt_data *md = input_get_drvdata(input); - mutex_lock(&md->report_lock); - if (!md->is_suspended) - pm_runtime_put(input->dev.parent); - mutex_unlock(&md->report_lock); -} - - -static int cyttsp4_setup_input_device(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - struct cyttsp4_mt_data *md = &cd->md; - int signal = CY_IGNORE_VALUE; - int max_x, max_y, max_p, min, max; - int max_x_tmp, max_y_tmp; - int i; - int rc; - - dev_vdbg(dev, "%s: Initialize event signals\n", __func__); - __set_bit(EV_ABS, md->input->evbit); - __set_bit(EV_REL, md->input->evbit); - __set_bit(EV_KEY, md->input->evbit); - - max_x_tmp = md->si->si_ofs.max_x; - max_y_tmp = md->si->si_ofs.max_y; - - /* get maximum values from the sysinfo data */ - if (md->pdata->flags & CY_FLAG_FLIP) { - max_x = max_y_tmp - 1; - max_y = max_x_tmp - 1; - } else { - max_x = max_x_tmp - 1; - max_y = max_y_tmp - 1; - } - max_p = md->si->si_ofs.max_p; - - /* set event signal capabilities */ - for (i = 0; i < (md->pdata->frmwrk->size / CY_NUM_ABS_SET); i++) { - signal = md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_SIGNAL_OST]; - if (signal != CY_IGNORE_VALUE) { - __set_bit(signal, md->input->absbit); - min = md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_MIN_OST]; - max = md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_MAX_OST]; - if (i == CY_ABS_ID_OST) { - /* shift track ids down to start at 0 */ - max = max - min; - min = min - min; - } else if (i == CY_ABS_X_OST) - max = max_x; - else if (i == CY_ABS_Y_OST) - max = max_y; - else if (i == CY_ABS_P_OST) - max = max_p; - input_set_abs_params(md->input, signal, min, max, - md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_FUZZ_OST], - md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_FLAT_OST]); - dev_dbg(dev, "%s: register signal=%02X min=%d max=%d\n", - __func__, signal, min, max); - if ((i == CY_ABS_ID_OST) && - (md->si->si_ofs.tch_rec_size < - CY_TMA4XX_TCH_REC_SIZE)) - break; - } - } - - input_mt_init_slots(md->input, md->si->si_ofs.tch_abs[CY_TCH_T].max, - INPUT_MT_DIRECT); - rc = input_register_device(md->input); - if (rc < 0) - dev_err(dev, "%s: Error, failed register input device r=%d\n", - __func__, rc); - return rc; -} - -static int cyttsp4_mt_probe(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - struct cyttsp4_mt_data *md = &cd->md; - struct cyttsp4_mt_platform_data *pdata = cd->pdata->mt_pdata; - int rc = 0; - - mutex_init(&md->report_lock); - md->pdata = pdata; - /* Create the input device and register it. */ - dev_vdbg(dev, "%s: Create the input device and register it\n", - __func__); - md->input = input_allocate_device(); - if (md->input == NULL) { - dev_err(dev, "%s: Error, failed to allocate input device\n", - __func__); - rc = -ENOSYS; - goto error_alloc_failed; - } - - md->input->name = pdata->inp_dev_name; - scnprintf(md->phys, sizeof(md->phys)-1, "%s", dev_name(dev)); - md->input->phys = md->phys; - md->input->id.bustype = cd->bus_ops->bustype; - md->input->dev.parent = dev; - md->input->open = cyttsp4_mt_open; - md->input->close = cyttsp4_mt_close; - input_set_drvdata(md->input, md); - - /* get sysinfo */ - md->si = &cd->sysinfo; - - rc = cyttsp4_setup_input_device(cd); - if (rc) - goto error_init_input; - - return 0; - -error_init_input: - input_free_device(md->input); -error_alloc_failed: - dev_err(dev, "%s failed.\n", __func__); - return rc; -} - -struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops, - struct device *dev, u16 irq, size_t xfer_buf_size) -{ - struct cyttsp4 *cd; - struct cyttsp4_platform_data *pdata = dev_get_platdata(dev); - unsigned long irq_flags; - int rc = 0; - - if (!pdata || !pdata->core_pdata || !pdata->mt_pdata) { - dev_err(dev, "%s: Missing platform data\n", __func__); - rc = -ENODEV; - goto error_no_pdata; - } - - cd = kzalloc(sizeof(*cd), GFP_KERNEL); - if (!cd) { - dev_err(dev, "%s: Error, kzalloc\n", __func__); - rc = -ENOMEM; - goto error_alloc_data; - } - - cd->xfer_buf = kzalloc(xfer_buf_size, GFP_KERNEL); - if (!cd->xfer_buf) { - dev_err(dev, "%s: Error, kzalloc\n", __func__); - rc = -ENOMEM; - goto error_free_cd; - } - - /* Initialize device info */ - cd->dev = dev; - cd->pdata = pdata; - cd->cpdata = pdata->core_pdata; - cd->bus_ops = ops; - - /* Initialize mutexes and spinlocks */ - mutex_init(&cd->system_lock); - mutex_init(&cd->adap_lock); - - /* Initialize wait queue */ - init_waitqueue_head(&cd->wait_q); - - /* Initialize works */ - INIT_WORK(&cd->startup_work, cyttsp4_startup_work_function); - INIT_WORK(&cd->watchdog_work, cyttsp4_watchdog_work); - - /* Initialize IRQ */ - cd->irq = gpio_to_irq(cd->cpdata->irq_gpio); - if (cd->irq < 0) { - rc = -EINVAL; - goto error_free_xfer; - } - - dev_set_drvdata(dev, cd); - - /* Call platform init function */ - if (cd->cpdata->init) { - dev_dbg(cd->dev, "%s: Init HW\n", __func__); - rc = cd->cpdata->init(cd->cpdata, 1, cd->dev); - } else { - dev_dbg(cd->dev, "%s: No HW INIT function\n", __func__); - rc = 0; - } - if (rc < 0) - dev_err(cd->dev, "%s: HW Init fail r=%d\n", __func__, rc); - - dev_dbg(dev, "%s: initialize threaded irq=%d\n", __func__, cd->irq); - if (cd->cpdata->level_irq_udelay > 0) - /* use level triggered interrupts */ - irq_flags = IRQF_TRIGGER_LOW | IRQF_ONESHOT; - else - /* use edge triggered interrupts */ - irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; - - rc = request_threaded_irq(cd->irq, NULL, cyttsp4_irq, irq_flags, - dev_name(dev), cd); - if (rc < 0) { - dev_err(dev, "%s: Error, could not request irq\n", __func__); - goto error_request_irq; - } - - /* Setup watchdog timer */ - timer_setup(&cd->watchdog_timer, cyttsp4_watchdog_timer, 0); - - /* - * call startup directly to ensure that the device - * is tested before leaving the probe - */ - rc = cyttsp4_startup(cd); - - /* Do not fail probe if startup fails but the device is detected */ - if (rc < 0 && cd->mode == CY_MODE_UNKNOWN) { - dev_err(cd->dev, "%s: Fail initial startup r=%d\n", - __func__, rc); - goto error_startup; - } - - rc = cyttsp4_mt_probe(cd); - if (rc < 0) { - dev_err(dev, "%s: Error, fail mt probe\n", __func__); - goto error_startup; - } - - pm_runtime_enable(dev); - - return cd; - -error_startup: - cancel_work_sync(&cd->startup_work); - cyttsp4_stop_wd_timer(cd); - pm_runtime_disable(dev); - cyttsp4_free_si_ptrs(cd); - free_irq(cd->irq, cd); -error_request_irq: - if (cd->cpdata->init) - cd->cpdata->init(cd->cpdata, 0, dev); -error_free_xfer: - kfree(cd->xfer_buf); -error_free_cd: - kfree(cd); -error_alloc_data: -error_no_pdata: - dev_err(dev, "%s failed.\n", __func__); - return ERR_PTR(rc); -} -EXPORT_SYMBOL_GPL(cyttsp4_probe); - -static void cyttsp4_mt_release(struct cyttsp4_mt_data *md) -{ - input_unregister_device(md->input); - input_set_drvdata(md->input, NULL); -} - -int cyttsp4_remove(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - - cyttsp4_mt_release(&cd->md); - - /* - * Suspend the device before freeing the startup_work and stopping - * the watchdog since sleep function restarts watchdog on failure - */ - pm_runtime_suspend(dev); - pm_runtime_disable(dev); - - cancel_work_sync(&cd->startup_work); - - cyttsp4_stop_wd_timer(cd); - - free_irq(cd->irq, cd); - if (cd->cpdata->init) - cd->cpdata->init(cd->cpdata, 0, dev); - cyttsp4_free_si_ptrs(cd); - kfree(cd); - return 0; -} -EXPORT_SYMBOL_GPL(cyttsp4_remove); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen core driver"); -MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/cyttsp4_core.h b/drivers/input/touchscreen/cyttsp4_core.h deleted file mode 100644 index 6262f6e45075..000000000000 --- a/drivers/input/touchscreen/cyttsp4_core.h +++ /dev/null @@ -1,448 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * cyttsp4_core.h - * Cypress TrueTouch(TM) Standard Product V4 Core driver module. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2012 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com - */ - -#ifndef _LINUX_CYTTSP4_CORE_H -#define _LINUX_CYTTSP4_CORE_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CY_REG_BASE 0x00 - -#define CY_POST_CODEL_WDG_RST 0x01 -#define CY_POST_CODEL_CFG_DATA_CRC_FAIL 0x02 -#define CY_POST_CODEL_PANEL_TEST_FAIL 0x04 - -#define CY_NUM_BTN_PER_REG 4 - -/* touch record system information offset masks and shifts */ -#define CY_BYTE_OFS_MASK 0x1F -#define CY_BOFS_MASK 0xE0 -#define CY_BOFS_SHIFT 5 - -#define CY_TMA1036_TCH_REC_SIZE 6 -#define CY_TMA4XX_TCH_REC_SIZE 9 -#define CY_TMA1036_MAX_TCH 0x0E -#define CY_TMA4XX_MAX_TCH 0x1E - -#define CY_NORMAL_ORIGIN 0 /* upper, left corner */ -#define CY_INVERT_ORIGIN 1 /* lower, right corner */ - -/* helpers */ -#define GET_NUM_TOUCHES(x) ((x) & 0x1F) -#define IS_LARGE_AREA(x) ((x) & 0x20) -#define IS_BAD_PKT(x) ((x) & 0x20) -#define IS_BOOTLOADER(hst_mode, reset_detect) \ - ((hst_mode) & 0x01 || (reset_detect) != 0) -#define IS_TMO(t) ((t) == 0) - - -enum cyttsp_cmd_bits { - CY_CMD_COMPLETE = (1 << 6), -}; - -/* Timeout in ms. */ -#define CY_WATCHDOG_TIMEOUT 1000 - -#define CY_MAX_PRINT_SIZE 512 -#ifdef VERBOSE_DEBUG -#define CY_MAX_PRBUF_SIZE PIPE_BUF -#define CY_PR_TRUNCATED " truncated..." -#endif - -enum cyttsp4_ic_grpnum { - CY_IC_GRPNUM_RESERVED, - CY_IC_GRPNUM_CMD_REGS, - CY_IC_GRPNUM_TCH_REP, - CY_IC_GRPNUM_DATA_REC, - CY_IC_GRPNUM_TEST_REC, - CY_IC_GRPNUM_PCFG_REC, - CY_IC_GRPNUM_TCH_PARM_VAL, - CY_IC_GRPNUM_TCH_PARM_SIZE, - CY_IC_GRPNUM_RESERVED1, - CY_IC_GRPNUM_RESERVED2, - CY_IC_GRPNUM_OPCFG_REC, - CY_IC_GRPNUM_DDATA_REC, - CY_IC_GRPNUM_MDATA_REC, - CY_IC_GRPNUM_TEST_REGS, - CY_IC_GRPNUM_BTN_KEYS, - CY_IC_GRPNUM_TTHE_REGS, - CY_IC_GRPNUM_NUM -}; - -enum cyttsp4_int_state { - CY_INT_NONE, - CY_INT_IGNORE = (1 << 0), - CY_INT_MODE_CHANGE = (1 << 1), - CY_INT_EXEC_CMD = (1 << 2), - CY_INT_AWAKE = (1 << 3), -}; - -enum cyttsp4_mode { - CY_MODE_UNKNOWN, - CY_MODE_BOOTLOADER = (1 << 1), - CY_MODE_OPERATIONAL = (1 << 2), - CY_MODE_SYSINFO = (1 << 3), - CY_MODE_CAT = (1 << 4), - CY_MODE_STARTUP = (1 << 5), - CY_MODE_LOADER = (1 << 6), - CY_MODE_CHANGE_MODE = (1 << 7), - CY_MODE_CHANGED = (1 << 8), - CY_MODE_CMD_COMPLETE = (1 << 9), -}; - -enum cyttsp4_sleep_state { - SS_SLEEP_OFF, - SS_SLEEP_ON, - SS_SLEEPING, - SS_WAKING, -}; - -enum cyttsp4_startup_state { - STARTUP_NONE, - STARTUP_QUEUED, - STARTUP_RUNNING, -}; - -#define CY_NUM_REVCTRL 8 -struct cyttsp4_cydata { - u8 ttpidh; - u8 ttpidl; - u8 fw_ver_major; - u8 fw_ver_minor; - u8 revctrl[CY_NUM_REVCTRL]; - u8 blver_major; - u8 blver_minor; - u8 jtag_si_id3; - u8 jtag_si_id2; - u8 jtag_si_id1; - u8 jtag_si_id0; - u8 mfgid_sz; - u8 cyito_idh; - u8 cyito_idl; - u8 cyito_verh; - u8 cyito_verl; - u8 ttsp_ver_major; - u8 ttsp_ver_minor; - u8 device_info; - u8 mfg_id[]; -} __packed; - -struct cyttsp4_test { - u8 post_codeh; - u8 post_codel; -} __packed; - -struct cyttsp4_pcfg { - u8 electrodes_x; - u8 electrodes_y; - u8 len_xh; - u8 len_xl; - u8 len_yh; - u8 len_yl; - u8 res_xh; - u8 res_xl; - u8 res_yh; - u8 res_yl; - u8 max_zh; - u8 max_zl; - u8 panel_info0; -} __packed; - -struct cyttsp4_tch_rec_params { - u8 loc; - u8 size; -} __packed; - -#define CY_NUM_TCH_FIELDS 7 -#define CY_NUM_EXT_TCH_FIELDS 3 -struct cyttsp4_opcfg { - u8 cmd_ofs; - u8 rep_ofs; - u8 rep_szh; - u8 rep_szl; - u8 num_btns; - u8 tt_stat_ofs; - u8 obj_cfg0; - u8 max_tchs; - u8 tch_rec_size; - struct cyttsp4_tch_rec_params tch_rec_old[CY_NUM_TCH_FIELDS]; - u8 btn_rec_size; /* btn record size (in bytes) */ - u8 btn_diff_ofs; /* btn data loc, diff counts */ - u8 btn_diff_size; /* btn size of diff counts (in bits) */ - struct cyttsp4_tch_rec_params tch_rec_new[CY_NUM_EXT_TCH_FIELDS]; -} __packed; - -struct cyttsp4_sysinfo_ptr { - struct cyttsp4_cydata *cydata; - struct cyttsp4_test *test; - struct cyttsp4_pcfg *pcfg; - struct cyttsp4_opcfg *opcfg; - struct cyttsp4_ddata *ddata; - struct cyttsp4_mdata *mdata; -} __packed; - -struct cyttsp4_sysinfo_data { - u8 hst_mode; - u8 reserved; - u8 map_szh; - u8 map_szl; - u8 cydata_ofsh; - u8 cydata_ofsl; - u8 test_ofsh; - u8 test_ofsl; - u8 pcfg_ofsh; - u8 pcfg_ofsl; - u8 opcfg_ofsh; - u8 opcfg_ofsl; - u8 ddata_ofsh; - u8 ddata_ofsl; - u8 mdata_ofsh; - u8 mdata_ofsl; -} __packed; - -enum cyttsp4_tch_abs { /* for ordering within the extracted touch data array */ - CY_TCH_X, /* X */ - CY_TCH_Y, /* Y */ - CY_TCH_P, /* P (Z) */ - CY_TCH_T, /* TOUCH ID */ - CY_TCH_E, /* EVENT ID */ - CY_TCH_O, /* OBJECT ID */ - CY_TCH_W, /* SIZE */ - CY_TCH_MAJ, /* TOUCH_MAJOR */ - CY_TCH_MIN, /* TOUCH_MINOR */ - CY_TCH_OR, /* ORIENTATION */ - CY_TCH_NUM_ABS -}; - -struct cyttsp4_touch { - int abs[CY_TCH_NUM_ABS]; -}; - -struct cyttsp4_tch_abs_params { - size_t ofs; /* abs byte offset */ - size_t size; /* size in bits */ - size_t max; /* max value */ - size_t bofs; /* bit offset */ -}; - -struct cyttsp4_sysinfo_ofs { - size_t chip_type; - size_t cmd_ofs; - size_t rep_ofs; - size_t rep_sz; - size_t num_btns; - size_t num_btn_regs; /* ceil(num_btns/4) */ - size_t tt_stat_ofs; - size_t tch_rec_size; - size_t obj_cfg0; - size_t max_tchs; - size_t mode_size; - size_t data_size; - size_t map_sz; - size_t max_x; - size_t x_origin; /* left or right corner */ - size_t max_y; - size_t y_origin; /* upper or lower corner */ - size_t max_p; - size_t cydata_ofs; - size_t test_ofs; - size_t pcfg_ofs; - size_t opcfg_ofs; - size_t ddata_ofs; - size_t mdata_ofs; - size_t cydata_size; - size_t test_size; - size_t pcfg_size; - size_t opcfg_size; - size_t ddata_size; - size_t mdata_size; - size_t btn_keys_size; - struct cyttsp4_tch_abs_params tch_abs[CY_TCH_NUM_ABS]; - size_t btn_rec_size; /* btn record size (in bytes) */ - size_t btn_diff_ofs;/* btn data loc ,diff counts, (Op-Mode byte ofs) */ - size_t btn_diff_size;/* btn size of diff counts (in bits) */ -}; - -enum cyttsp4_btn_state { - CY_BTN_RELEASED, - CY_BTN_PRESSED, - CY_BTN_NUM_STATE -}; - -struct cyttsp4_btn { - bool enabled; - int state; /* CY_BTN_PRESSED, CY_BTN_RELEASED */ - int key_code; -}; - -struct cyttsp4_sysinfo { - bool ready; - struct cyttsp4_sysinfo_data si_data; - struct cyttsp4_sysinfo_ptr si_ptrs; - struct cyttsp4_sysinfo_ofs si_ofs; - struct cyttsp4_btn *btn; /* button states */ - u8 *btn_rec_data; /* button diff count data */ - u8 *xy_mode; /* operational mode and status regs */ - u8 *xy_data; /* operational touch regs */ -}; - -struct cyttsp4_mt_data { - struct cyttsp4_mt_platform_data *pdata; - struct cyttsp4_sysinfo *si; - struct input_dev *input; - struct mutex report_lock; - bool is_suspended; - char phys[NAME_MAX]; - int num_prv_tch; -}; - -struct cyttsp4 { - struct device *dev; - struct mutex system_lock; - struct mutex adap_lock; - enum cyttsp4_mode mode; - enum cyttsp4_sleep_state sleep_state; - enum cyttsp4_startup_state startup_state; - int int_status; - wait_queue_head_t wait_q; - int irq; - struct work_struct startup_work; - struct work_struct watchdog_work; - struct timer_list watchdog_timer; - struct cyttsp4_sysinfo sysinfo; - void *exclusive_dev; - int exclusive_waits; - atomic_t ignore_irq; - bool invalid_touch_app; - struct cyttsp4_mt_data md; - struct cyttsp4_platform_data *pdata; - struct cyttsp4_core_platform_data *cpdata; - const struct cyttsp4_bus_ops *bus_ops; - u8 *xfer_buf; -#ifdef VERBOSE_DEBUG - u8 pr_buf[CY_MAX_PRBUF_SIZE]; -#endif -}; - -struct cyttsp4_bus_ops { - u16 bustype; - int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, - const void *values); - int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, - void *values); -}; - -enum cyttsp4_hst_mode_bits { - CY_HST_TOGGLE = (1 << 7), - CY_HST_MODE_CHANGE = (1 << 3), - CY_HST_MODE = (7 << 4), - CY_HST_OPERATE = (0 << 4), - CY_HST_SYSINFO = (1 << 4), - CY_HST_CAT = (2 << 4), - CY_HST_LOWPOW = (1 << 2), - CY_HST_SLEEP = (1 << 1), - CY_HST_RESET = (1 << 0), -}; - -/* abs settings */ -#define CY_IGNORE_VALUE 0xFFFF - -/* abs signal capabilities offsets in the frameworks array */ -enum cyttsp4_sig_caps { - CY_SIGNAL_OST, - CY_MIN_OST, - CY_MAX_OST, - CY_FUZZ_OST, - CY_FLAT_OST, - CY_NUM_ABS_SET /* number of signal capability fields */ -}; - -/* abs axis signal offsets in the framworks array */ -enum cyttsp4_sig_ost { - CY_ABS_X_OST, - CY_ABS_Y_OST, - CY_ABS_P_OST, - CY_ABS_W_OST, - CY_ABS_ID_OST, - CY_ABS_MAJ_OST, - CY_ABS_MIN_OST, - CY_ABS_OR_OST, - CY_NUM_ABS_OST /* number of abs signals */ -}; - -enum cyttsp4_flags { - CY_FLAG_NONE = 0x00, - CY_FLAG_HOVER = 0x04, - CY_FLAG_FLIP = 0x08, - CY_FLAG_INV_X = 0x10, - CY_FLAG_INV_Y = 0x20, - CY_FLAG_VKEYS = 0x40, -}; - -enum cyttsp4_object_id { - CY_OBJ_STANDARD_FINGER, - CY_OBJ_LARGE_OBJECT, - CY_OBJ_STYLUS, - CY_OBJ_HOVER, -}; - -enum cyttsp4_event_id { - CY_EV_NO_EVENT, - CY_EV_TOUCHDOWN, - CY_EV_MOVE, /* significant displacement (> act dist) */ - CY_EV_LIFTOFF, /* record reports last position */ -}; - -/* x-axis resolution of panel in pixels */ -#define CY_PCFG_RESOLUTION_X_MASK 0x7F - -/* y-axis resolution of panel in pixels */ -#define CY_PCFG_RESOLUTION_Y_MASK 0x7F - -/* x-axis, 0:origin is on left side of panel, 1: right */ -#define CY_PCFG_ORIGIN_X_MASK 0x80 - -/* y-axis, 0:origin is on top side of panel, 1: bottom */ -#define CY_PCFG_ORIGIN_Y_MASK 0x80 - -static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u16 addr, int size, - void *buf) -{ - return ts->bus_ops->read(ts->dev, ts->xfer_buf, addr, size, buf); -} - -static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u16 addr, int size, - const void *buf) -{ - return ts->bus_ops->write(ts->dev, ts->xfer_buf, addr, size, buf); -} - -extern struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops, - struct device *dev, u16 irq, size_t xfer_buf_size); -extern int cyttsp4_remove(struct cyttsp4 *ts); -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, const void *values); -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, void *values); -extern const struct dev_pm_ops cyttsp4_pm_ops; - -#endif /* _LINUX_CYTTSP4_CORE_H */ diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c deleted file mode 100644 index da32c151def5..000000000000 --- a/drivers/input/touchscreen/cyttsp4_i2c.c +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cyttsp_i2c.c - * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas - * Copyright (C) 2013 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com - */ - -#include "cyttsp4_core.h" - -#include -#include - -#define CYTTSP4_I2C_DATA_SIZE (3 * 256) - -static const struct cyttsp4_bus_ops cyttsp4_i2c_bus_ops = { - .bustype = BUS_I2C, - .write = cyttsp_i2c_write_block_data, - .read = cyttsp_i2c_read_block_data, -}; - -static int cyttsp4_i2c_probe(struct i2c_client *client) -{ - struct cyttsp4 *ts; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(&client->dev, "I2C functionality not Supported\n"); - return -EIO; - } - - ts = cyttsp4_probe(&cyttsp4_i2c_bus_ops, &client->dev, client->irq, - CYTTSP4_I2C_DATA_SIZE); - - return PTR_ERR_OR_ZERO(ts); -} - -static void cyttsp4_i2c_remove(struct i2c_client *client) -{ - struct cyttsp4 *ts = i2c_get_clientdata(client); - - cyttsp4_remove(ts); -} - -static const struct i2c_device_id cyttsp4_i2c_id[] = { - { CYTTSP4_I2C_NAME }, - { } -}; -MODULE_DEVICE_TABLE(i2c, cyttsp4_i2c_id); - -static struct i2c_driver cyttsp4_i2c_driver = { - .driver = { - .name = CYTTSP4_I2C_NAME, - .pm = pm_ptr(&cyttsp4_pm_ops), - }, - .probe = cyttsp4_i2c_probe, - .remove = cyttsp4_i2c_remove, - .id_table = cyttsp4_i2c_id, -}; - -module_i2c_driver(cyttsp4_i2c_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver"); -MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c deleted file mode 100644 index 944fbbe9113e..000000000000 --- a/drivers/input/touchscreen/cyttsp4_spi.c +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Source for: - * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas - * Copyright (C) 2013 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com - */ - -#include "cyttsp4_core.h" - -#include -#include -#include - -#define CY_SPI_WR_OP 0x00 /* r/~w */ -#define CY_SPI_RD_OP 0x01 -#define CY_SPI_BITS_PER_WORD 8 -#define CY_SPI_A8_BIT 0x02 -#define CY_SPI_WR_HEADER_BYTES 2 -#define CY_SPI_RD_HEADER_BYTES 1 -#define CY_SPI_CMD_BYTES 2 -#define CY_SPI_SYNC_BYTE 0 -#define CY_SPI_SYNC_ACK 0x62 /* from TRM *A protocol */ -#define CY_SPI_DATA_SIZE (2 * 256) - -#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) - -static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, - u8 op, u16 reg, u8 *buf, int length) -{ - struct spi_device *spi = to_spi_device(dev); - struct spi_message msg; - struct spi_transfer xfer[2]; - u8 *wr_buf = &xfer_buf[0]; - u8 rd_buf[CY_SPI_CMD_BYTES]; - int retval; - int i; - - if (length > CY_SPI_DATA_SIZE) { - dev_err(dev, "%s: length %d is too big.\n", - __func__, length); - return -EINVAL; - } - - memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE); - memset(rd_buf, 0, CY_SPI_CMD_BYTES); - - wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0); - if (op == CY_SPI_WR_OP) { - wr_buf[1] = reg & 0xFF; - if (length > 0) - memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); - } - - memset(xfer, 0, sizeof(xfer)); - spi_message_init(&msg); - - /* - We set both TX and RX buffers because Cypress TTSP - requires full duplex operation. - */ - xfer[0].tx_buf = wr_buf; - xfer[0].rx_buf = rd_buf; - switch (op) { - case CY_SPI_WR_OP: - xfer[0].len = length + CY_SPI_CMD_BYTES; - spi_message_add_tail(&xfer[0], &msg); - break; - - case CY_SPI_RD_OP: - xfer[0].len = CY_SPI_RD_HEADER_BYTES; - spi_message_add_tail(&xfer[0], &msg); - - xfer[1].rx_buf = buf; - xfer[1].len = length; - spi_message_add_tail(&xfer[1], &msg); - break; - - default: - dev_err(dev, "%s: bad operation code=%d\n", __func__, op); - return -EINVAL; - } - - retval = spi_sync(spi, &msg); - if (retval < 0) { - dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n", - __func__, retval, xfer[1].len, op); - - /* - * do not return here since was a bad ACK sequence - * let the following ACK check handle any errors and - * allow silent retries - */ - } - - if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK) { - dev_dbg(dev, "%s: operation %d failed\n", __func__, op); - - for (i = 0; i < CY_SPI_CMD_BYTES; i++) - dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n", - __func__, i, rd_buf[i]); - for (i = 0; i < length; i++) - dev_dbg(dev, "%s: test buf[%d]:0x%02x\n", - __func__, i, buf[i]); - - return -EIO; - } - - return 0; -} - -static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, void *data) -{ - int rc; - - rc = cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, NULL, 0); - if (rc) - return rc; - else - return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data, - length); -} - -static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, const void *data) -{ - return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data, - length); -} - -static const struct cyttsp4_bus_ops cyttsp_spi_bus_ops = { - .bustype = BUS_SPI, - .write = cyttsp_spi_write_block_data, - .read = cyttsp_spi_read_block_data, -}; - -static int cyttsp4_spi_probe(struct spi_device *spi) -{ - struct cyttsp4 *ts; - int error; - - /* Set up SPI*/ - spi->bits_per_word = CY_SPI_BITS_PER_WORD; - spi->mode = SPI_MODE_0; - error = spi_setup(spi); - if (error < 0) { - dev_err(&spi->dev, "%s: SPI setup error %d\n", - __func__, error); - return error; - } - - ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, - CY_SPI_DATA_BUF_SIZE); - - return PTR_ERR_OR_ZERO(ts); -} - -static void cyttsp4_spi_remove(struct spi_device *spi) -{ - struct cyttsp4 *ts = spi_get_drvdata(spi); - cyttsp4_remove(ts); -} - -static struct spi_driver cyttsp4_spi_driver = { - .driver = { - .name = CYTTSP4_SPI_NAME, - .pm = pm_ptr(&cyttsp4_pm_ops), - }, - .probe = cyttsp4_spi_probe, - .remove = cyttsp4_spi_remove, -}; - -module_spi_driver(cyttsp4_spi_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); -MODULE_AUTHOR("Cypress"); -MODULE_ALIAS("spi:cyttsp4"); diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index cd3b80401970..40a605d20285 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -136,10 +136,6 @@ struct cyttsp { struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size); -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, const void *values); -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, void *values); extern const struct dev_pm_ops cyttsp_pm_ops; #endif /* __CYTTSP_CORE_H__ */ diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index bf13b3448a6b..cb15600549cd 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -22,6 +22,61 @@ #define CY_I2C_DATA_SIZE 128 +static int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, + u16 addr, u8 length, void *values) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 client_addr = client->addr | ((addr >> 8) & 0x1); + u8 addr_lo = addr & 0xFF; + struct i2c_msg msgs[] = { + { + .addr = client_addr, + .flags = 0, + .len = 1, + .buf = &addr_lo, + }, + { + .addr = client_addr, + .flags = I2C_M_RD, + .len = length, + .buf = values, + }, + }; + int retval; + + retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (retval < 0) + return retval; + + return retval != ARRAY_SIZE(msgs) ? -EIO : 0; +} + +static int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, + u16 addr, u8 length, const void *values) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 client_addr = client->addr | ((addr >> 8) & 0x1); + u8 addr_lo = addr & 0xFF; + struct i2c_msg msgs[] = { + { + .addr = client_addr, + .flags = 0, + .len = length + 1, + .buf = xfer_buf, + }, + }; + int retval; + + xfer_buf[0] = addr_lo; + memcpy(&xfer_buf[1], values, length); + + retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (retval < 0) + return retval; + + return retval != ARRAY_SIZE(msgs) ? -EIO : 0; +} + static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { .bustype = BUS_I2C, .write = cyttsp_i2c_write_block_data, diff --git a/drivers/input/touchscreen/cyttsp_i2c_common.c b/drivers/input/touchscreen/cyttsp_i2c_common.c deleted file mode 100644 index 7e752fb9fad7..000000000000 --- a/drivers/input/touchscreen/cyttsp_i2c_common.c +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cyttsp_i2c_common.c - * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. - * For use with Cypress Txx3xx and Txx4xx parts. - * Supported parts include: - * CY8CTST341 - * CY8CTMA340 - * TMA4XX - * TMA1036 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas - * - * Contact Cypress Semiconductor at www.cypress.com - */ - -#include -#include -#include -#include -#include - -#include "cyttsp4_core.h" - -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, void *values) -{ - struct i2c_client *client = to_i2c_client(dev); - u8 client_addr = client->addr | ((addr >> 8) & 0x1); - u8 addr_lo = addr & 0xFF; - struct i2c_msg msgs[] = { - { - .addr = client_addr, - .flags = 0, - .len = 1, - .buf = &addr_lo, - }, - { - .addr = client_addr, - .flags = I2C_M_RD, - .len = length, - .buf = values, - }, - }; - int retval; - - retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (retval < 0) - return retval; - - return retval != ARRAY_SIZE(msgs) ? -EIO : 0; -} -EXPORT_SYMBOL_GPL(cyttsp_i2c_read_block_data); - -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, const void *values) -{ - struct i2c_client *client = to_i2c_client(dev); - u8 client_addr = client->addr | ((addr >> 8) & 0x1); - u8 addr_lo = addr & 0xFF; - struct i2c_msg msgs[] = { - { - .addr = client_addr, - .flags = 0, - .len = length + 1, - .buf = xfer_buf, - }, - }; - int retval; - - xfer_buf[0] = addr_lo; - memcpy(&xfer_buf[1], values, length); - - retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (retval < 0) - return retval; - - return retval != ARRAY_SIZE(msgs) ? -EIO : 0; -} -EXPORT_SYMBOL_GPL(cyttsp_i2c_write_block_data); - - -MODULE_DESCRIPTION("Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Cypress"); diff --git a/include/linux/platform_data/cyttsp4.h b/include/linux/platform_data/cyttsp4.h deleted file mode 100644 index 5dc9d2be384b..000000000000 --- a/include/linux/platform_data/cyttsp4.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Header file for: - * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. - * For use with Cypress Txx3xx parts. - * Supported parts include: - * CY8CTST341 - * CY8CTMA340 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas - * - * Contact Cypress Semiconductor at www.cypress.com (kev@cypress.com) - */ -#ifndef _CYTTSP4_H_ -#define _CYTTSP4_H_ - -#define CYTTSP4_MT_NAME "cyttsp4_mt" -#define CYTTSP4_I2C_NAME "cyttsp4_i2c_adapter" -#define CYTTSP4_SPI_NAME "cyttsp4_spi_adapter" - -#define CY_TOUCH_SETTINGS_MAX 32 - -struct touch_framework { - const uint16_t *abs; - uint8_t size; - uint8_t enable_vkeys; -} __packed; - -struct cyttsp4_mt_platform_data { - struct touch_framework *frmwrk; - unsigned short flags; - char const *inp_dev_name; -}; - -struct touch_settings { - const uint8_t *data; - uint32_t size; - uint8_t tag; -} __packed; - -struct cyttsp4_core_platform_data { - int irq_gpio; - int rst_gpio; - int level_irq_udelay; - int (*xres)(struct cyttsp4_core_platform_data *pdata, - struct device *dev); - int (*init)(struct cyttsp4_core_platform_data *pdata, - int on, struct device *dev); - int (*power)(struct cyttsp4_core_platform_data *pdata, - int on, struct device *dev, atomic_t *ignore_irq); - int (*irq_stat)(struct cyttsp4_core_platform_data *pdata, - struct device *dev); - struct touch_settings *sett[CY_TOUCH_SETTINGS_MAX]; -}; - -struct cyttsp4_platform_data { - struct cyttsp4_core_platform_data *core_pdata; - struct cyttsp4_mt_platform_data *mt_pdata; -}; - -#endif /* _CYTTSP4_H_ */ -- cgit v1.2.3 From 8c38617722bdf57a90e6c77ed9ee5ebb60958d2a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 9 Aug 2024 16:15:54 +0200 Subject: memory: ti-aemif: remove platform data support There are no longer any users of the ti-aemif driver that set up platform data from board files. We can shrink the driver by removing support for it. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20240809-ti-aemif-v1-1-27b1e5001390@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/memory/ti-aemif.c | 25 +------------------ include/linux/platform_data/ti-aemif.h | 45 ---------------------------------- 2 files changed, 1 insertion(+), 69 deletions(-) delete mode 100644 include/linux/platform_data/ti-aemif.h (limited to 'include/linux/platform_data') diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index e192db9e0e4b..b92cab455cbb 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -17,7 +17,6 @@ #include #include #include -#include #define TA_SHIFT 2 #define RHOLD_SHIFT 4 @@ -332,16 +331,11 @@ static int aemif_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; struct device_node *child_np; struct aemif_device *aemif; - struct aemif_platform_data *pdata; - struct of_dev_auxdata *dev_lookup; aemif = devm_kzalloc(dev, sizeof(*aemif), GFP_KERNEL); if (!aemif) return -ENOMEM; - pdata = dev_get_platdata(&pdev->dev); - dev_lookup = pdata ? pdata->dev_lookup : NULL; - platform_set_drvdata(pdev, aemif); aemif->clk = devm_clk_get(dev, NULL); @@ -358,8 +352,6 @@ static int aemif_probe(struct platform_device *pdev) if (np && of_device_is_compatible(np, "ti,da850-aemif")) aemif->cs_offset = 2; - else if (pdata) - aemif->cs_offset = pdata->cs_offset; aemif->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(aemif->base)) { @@ -381,11 +373,6 @@ static int aemif_probe(struct platform_device *pdev) goto error; } } - } else if (pdata && pdata->num_abus_data > 0) { - for (i = 0; i < pdata->num_abus_data; i++, aemif->num_cs++) { - aemif->cs_data[i].cs = pdata->abus_data[i].cs; - aemif_get_hw_params(pdev, i); - } } for (i = 0; i < aemif->num_cs; i++) { @@ -403,22 +390,12 @@ static int aemif_probe(struct platform_device *pdev) */ if (np) { for_each_available_child_of_node(np, child_np) { - ret = of_platform_populate(child_np, NULL, - dev_lookup, dev); + ret = of_platform_populate(child_np, NULL, NULL, dev); if (ret < 0) { of_node_put(child_np); goto error; } } - } else if (pdata) { - for (i = 0; i < pdata->num_sub_devices; i++) { - pdata->sub_devices[i].dev.parent = dev; - ret = platform_device_register(&pdata->sub_devices[i]); - if (ret) { - dev_warn(dev, "Error register sub device %s\n", - pdata->sub_devices[i].name); - } - } } return 0; diff --git a/include/linux/platform_data/ti-aemif.h b/include/linux/platform_data/ti-aemif.h deleted file mode 100644 index 77625251df07..000000000000 --- a/include/linux/platform_data/ti-aemif.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * TI DaVinci AEMIF platform glue. - * - * Copyright (C) 2017 BayLibre SAS - * - * Author: - * Bartosz Golaszewski - */ - -#ifndef __TI_DAVINCI_AEMIF_DATA_H__ -#define __TI_DAVINCI_AEMIF_DATA_H__ - -#include - -/** - * struct aemif_abus_data - Async bus configuration parameters. - * - * @cs - Chip-select number. - */ -struct aemif_abus_data { - u32 cs; -}; - -/** - * struct aemif_platform_data - Data to set up the TI aemif driver. - * - * @dev_lookup: of_dev_auxdata passed to of_platform_populate() for aemif - * subdevices. - * @cs_offset: Lowest allowed chip-select number. - * @abus_data: Array of async bus configuration entries. - * @num_abus_data: Number of abus entries. - * @sub_devices: Array of platform subdevices. - * @num_sub_devices: Number of subdevices. - */ -struct aemif_platform_data { - struct of_dev_auxdata *dev_lookup; - u32 cs_offset; - struct aemif_abus_data *abus_data; - size_t num_abus_data; - struct platform_device *sub_devices; - size_t num_sub_devices; -}; - -#endif /* __TI_DAVINCI_AEMIF_DATA_H__ */ -- cgit v1.2.3 From 6c65914a40d33e96ceedc757be0129139cdf7852 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 16 Aug 2024 11:54:23 -0700 Subject: Input: keypad-nomadik-ske - remove the driver The users of this driver were removed in 2013 in commit 28633c54bda6 ("ARM: ux500: Rip out keypad initialisation which is no longer used"). Remove the driver as well. Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/Zr-gX0dfN4te_8VG@google.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 11 - drivers/input/keyboard/Makefile | 1 - drivers/input/keyboard/nomadik-ske-keypad.c | 378 ----------------------- include/linux/platform_data/keypad-nomadik-ske.h | 50 --- 4 files changed, 440 deletions(-) delete mode 100644 drivers/input/keyboard/nomadik-ske-keypad.c delete mode 100644 include/linux/platform_data/keypad-nomadik-ske.h (limited to 'include/linux/platform_data') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 72f9552cb571..a5015d6f8bed 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -473,17 +473,6 @@ config KEYBOARD_NEWTON To compile this driver as a module, choose M here: the module will be called newtonkbd. -config KEYBOARD_NOMADIK - tristate "ST-Ericsson Nomadik SKE keyboard" - depends on (ARCH_NOMADIK || ARCH_U8500 || COMPILE_TEST) - select INPUT_MATRIXKMAP - help - Say Y here if you want to use a keypad provided on the SKE controller - used on the Ux500 and Nomadik platforms - - To compile this driver as a module, choose M here: the - module will be called nmk-ske-keypad. - config KEYBOARD_NSPIRE tristate "TI-NSPIRE built-in keyboard" depends on ARCH_NSPIRE && OF diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index b8d12a0524e0..3631a9294c6f 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o obj-$(CONFIG_KEYBOARD_MT6779) += mt6779-keypad.o obj-$(CONFIG_KEYBOARD_MTK_PMIC) += mtk-pmic-keys.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o -obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c deleted file mode 100644 index b3ccc97f61e1..000000000000 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ /dev/null @@ -1,378 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Naveen Kumar G for ST-Ericsson - * Author: Sundar Iyer for ST-Ericsson - * - * Keypad controller driver for the SKE (Scroll Key Encoder) module used in - * the Nomadik 8815 and Ux500 platforms. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* SKE_CR bits */ -#define SKE_KPMLT (0x1 << 6) -#define SKE_KPCN (0x7 << 3) -#define SKE_KPASEN (0x1 << 2) -#define SKE_KPASON (0x1 << 7) - -/* SKE_IMSC bits */ -#define SKE_KPIMA (0x1 << 2) - -/* SKE_ICR bits */ -#define SKE_KPICS (0x1 << 3) -#define SKE_KPICA (0x1 << 2) - -/* SKE_RIS bits */ -#define SKE_KPRISA (0x1 << 2) - -#define SKE_KEYPAD_ROW_SHIFT 3 -#define SKE_KPD_NUM_ROWS 8 -#define SKE_KPD_NUM_COLS 8 - -/* keypad auto scan registers */ -#define SKE_ASR0 0x20 -#define SKE_ASR1 0x24 -#define SKE_ASR2 0x28 -#define SKE_ASR3 0x2C - -#define SKE_NUM_ASRX_REGISTERS (4) -#define KEY_PRESSED_DELAY 10 - -/** - * struct ske_keypad - data structure used by keypad driver - * @irq: irq no - * @reg_base: ske registers base address - * @input: pointer to input device object - * @board: keypad platform device - * @keymap: matrix scan code table for keycodes - * @clk: clock structure pointer - * @pclk: clock structure pointer - * @ske_keypad_lock: spinlock protecting the keypad read/writes - */ -struct ske_keypad { - int irq; - void __iomem *reg_base; - struct input_dev *input; - const struct ske_keypad_platform_data *board; - unsigned short keymap[SKE_KPD_NUM_ROWS * SKE_KPD_NUM_COLS]; - struct clk *clk; - struct clk *pclk; - spinlock_t ske_keypad_lock; -}; - -static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr, - u8 mask, u8 data) -{ - u32 ret; - - spin_lock(&keypad->ske_keypad_lock); - - ret = readl(keypad->reg_base + addr); - ret &= ~mask; - ret |= data; - writel(ret, keypad->reg_base + addr); - - spin_unlock(&keypad->ske_keypad_lock); -} - -/* - * ske_keypad_chip_init: init keypad controller configuration - * - * Enable Multi key press detection, auto scan mode - */ -static int __init ske_keypad_chip_init(struct ske_keypad *keypad) -{ - u32 value; - int timeout = keypad->board->debounce_ms; - - /* check SKE_RIS to be 0 */ - while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--) - cpu_relax(); - - if (timeout == -1) - return -EINVAL; - - /* - * set debounce value - * keypad dbounce is configured in DBCR[15:8] - * dbounce value in steps of 32/32.768 ms - */ - spin_lock(&keypad->ske_keypad_lock); - value = readl(keypad->reg_base + SKE_DBCR); - value = value & 0xff; - value |= ((keypad->board->debounce_ms * 32000)/32768) << 8; - writel(value, keypad->reg_base + SKE_DBCR); - spin_unlock(&keypad->ske_keypad_lock); - - /* enable multi key detection */ - ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPMLT); - - /* - * set up the number of columns - * KPCN[5:3] defines no. of keypad columns to be auto scanned - */ - value = (keypad->board->kcol - 1) << 3; - ske_keypad_set_bits(keypad, SKE_CR, SKE_KPCN, value); - - /* clear keypad interrupt for auto(and pending SW) scans */ - ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA | SKE_KPICS); - - /* un-mask keypad interrupts */ - ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA); - - /* enable automatic scan */ - ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPASEN); - - return 0; -} - -static void ske_keypad_report(struct ske_keypad *keypad, u8 status, int col) -{ - int row = 0, code, pos; - struct input_dev *input = keypad->input; - u32 ske_ris; - int key_pressed; - int num_of_rows; - - /* find out the row */ - num_of_rows = hweight8(status); - do { - pos = __ffs(status); - row = pos; - status &= ~(1 << pos); - - code = MATRIX_SCAN_CODE(row, col, SKE_KEYPAD_ROW_SHIFT); - ske_ris = readl(keypad->reg_base + SKE_RIS); - key_pressed = ske_ris & SKE_KPRISA; - - input_event(input, EV_MSC, MSC_SCAN, code); - input_report_key(input, keypad->keymap[code], key_pressed); - input_sync(input); - num_of_rows--; - } while (num_of_rows); -} - -static void ske_keypad_read_data(struct ske_keypad *keypad) -{ - u8 status; - int col = 0; - int ske_asr, i; - - /* - * Read the auto scan registers - * - * Each SKE_ASRx (x=0 to x=3) contains two row values. - * lower byte contains row value for column 2*x, - * upper byte contains row value for column 2*x + 1 - */ - for (i = 0; i < SKE_NUM_ASRX_REGISTERS; i++) { - ske_asr = readl(keypad->reg_base + SKE_ASR0 + (4 * i)); - if (!ske_asr) - continue; - - /* now that ASRx is zero, find out the coloumn x and row y */ - status = ske_asr & 0xff; - if (status) { - col = i * 2; - ske_keypad_report(keypad, status, col); - } - status = (ske_asr & 0xff00) >> 8; - if (status) { - col = (i * 2) + 1; - ske_keypad_report(keypad, status, col); - } - } -} - -static irqreturn_t ske_keypad_irq(int irq, void *dev_id) -{ - struct ske_keypad *keypad = dev_id; - int timeout = keypad->board->debounce_ms; - - /* disable auto scan interrupt; mask the interrupt generated */ - ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0); - ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA); - - while ((readl(keypad->reg_base + SKE_CR) & SKE_KPASON) && --timeout) - cpu_relax(); - - /* SKEx registers are stable and can be read */ - ske_keypad_read_data(keypad); - - /* wait until raw interrupt is clear */ - while ((readl(keypad->reg_base + SKE_RIS)) && --timeout) - msleep(KEY_PRESSED_DELAY); - - /* enable auto scan interrupts */ - ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA); - - return IRQ_HANDLED; -} - -static void ske_keypad_board_exit(void *data) -{ - struct ske_keypad *keypad = data; - - keypad->board->exit(); -} - -static int __init ske_keypad_probe(struct platform_device *pdev) -{ - const struct ske_keypad_platform_data *plat = - dev_get_platdata(&pdev->dev); - struct device *dev = &pdev->dev; - struct ske_keypad *keypad; - struct input_dev *input; - int irq; - int error; - - if (!plat) { - dev_err(&pdev->dev, "invalid keypad platform data\n"); - return -EINVAL; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - keypad = devm_kzalloc(dev, sizeof(struct ske_keypad), - GFP_KERNEL); - input = devm_input_allocate_device(dev); - if (!keypad || !input) { - dev_err(&pdev->dev, "failed to allocate keypad memory\n"); - return -ENOMEM; - } - - keypad->irq = irq; - keypad->board = plat; - keypad->input = input; - spin_lock_init(&keypad->ske_keypad_lock); - - keypad->reg_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(keypad->reg_base)) - return PTR_ERR(keypad->reg_base); - - keypad->pclk = devm_clk_get_enabled(dev, "apb_pclk"); - if (IS_ERR(keypad->pclk)) { - dev_err(&pdev->dev, "failed to get pclk\n"); - return PTR_ERR(keypad->pclk); - } - - keypad->clk = devm_clk_get_enabled(dev, NULL); - if (IS_ERR(keypad->clk)) { - dev_err(&pdev->dev, "failed to get clk\n"); - return PTR_ERR(keypad->clk); - } - - input->id.bustype = BUS_HOST; - input->name = "ux500-ske-keypad"; - input->dev.parent = &pdev->dev; - - error = matrix_keypad_build_keymap(plat->keymap_data, NULL, - SKE_KPD_NUM_ROWS, SKE_KPD_NUM_COLS, - keypad->keymap, input); - if (error) { - dev_err(&pdev->dev, "Failed to build keymap\n"); - return error; - } - - input_set_capability(input, EV_MSC, MSC_SCAN); - if (!plat->no_autorepeat) - __set_bit(EV_REP, input->evbit); - - /* go through board initialization helpers */ - if (keypad->board->init) - keypad->board->init(); - - if (keypad->board->exit) { - error = devm_add_action_or_reset(dev, ske_keypad_board_exit, - keypad); - if (error) - return error; - } - - error = ske_keypad_chip_init(keypad); - if (error) { - dev_err(&pdev->dev, "unable to init keypad hardware\n"); - return error; - } - - error = devm_request_threaded_irq(dev, keypad->irq, - NULL, ske_keypad_irq, - IRQF_ONESHOT, "ske-keypad", keypad); - if (error) { - dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq); - return error; - } - - error = input_register_device(input); - if (error) { - dev_err(&pdev->dev, - "unable to register input device: %d\n", error); - return error; - } - - if (plat->wakeup_enable) - device_init_wakeup(&pdev->dev, true); - - platform_set_drvdata(pdev, keypad); - - return 0; -} - -static int ske_keypad_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ske_keypad *keypad = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - - if (device_may_wakeup(dev)) - enable_irq_wake(irq); - else - ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0); - - return 0; -} - -static int ske_keypad_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ske_keypad *keypad = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - - if (device_may_wakeup(dev)) - disable_irq_wake(irq); - else - ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA); - - return 0; -} - -static DEFINE_SIMPLE_DEV_PM_OPS(ske_keypad_dev_pm_ops, - ske_keypad_suspend, ske_keypad_resume); - -static struct platform_driver ske_keypad_driver = { - .driver = { - .name = "nmk-ske-keypad", - .pm = pm_sleep_ptr(&ske_keypad_dev_pm_ops), - }, -}; - -module_platform_driver_probe(ske_keypad_driver, ske_keypad_probe); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Naveen Kumar / Sundar Iyer "); -MODULE_DESCRIPTION("Nomadik Scroll-Key-Encoder Keypad Driver"); -MODULE_ALIAS("platform:nomadik-ske-keypad"); diff --git a/include/linux/platform_data/keypad-nomadik-ske.h b/include/linux/platform_data/keypad-nomadik-ske.h deleted file mode 100644 index 7efabbca1dca..000000000000 --- a/include/linux/platform_data/keypad-nomadik-ske.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Naveen Kumar Gaddipati - * - * ux500 Scroll key and Keypad Encoder (SKE) header - */ - -#ifndef __SKE_H -#define __SKE_H - -#include - -/* register definitions for SKE peripheral */ -#define SKE_CR 0x00 -#define SKE_VAL0 0x04 -#define SKE_VAL1 0x08 -#define SKE_DBCR 0x0C -#define SKE_IMSC 0x10 -#define SKE_RIS 0x14 -#define SKE_MIS 0x18 -#define SKE_ICR 0x1C - -/* - * Keypad module - */ - -/** - * struct keypad_platform_data - structure for platform specific data - * @init: pointer to keypad init function - * @exit: pointer to keypad deinitialisation function - * @keymap_data: matrix scan code table for keycodes - * @krow: maximum number of rows - * @kcol: maximum number of columns - * @debounce_ms: platform specific debounce time - * @no_autorepeat: flag for auto repetition - * @wakeup_enable: allow waking up the system - */ -struct ske_keypad_platform_data { - int (*init)(void); - int (*exit)(void); - const struct matrix_keymap_data *keymap_data; - u8 krow; - u8 kcol; - u8 debounce_ms; - bool no_autorepeat; - bool wakeup_enable; -}; -#endif /*__SKE_KPD_H*/ -- cgit v1.2.3 From ccce71013406a0a3c81850dab940f07b112349d3 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 14 Aug 2024 14:21:18 +0200 Subject: mtd: rawnand: davinci: make platform_data private There are no longer any users of the platform data for davinci rawnand in board files. We can remove the public pdata headers and move the structures that are still used into the driver compilation unit while removing the rest. Signed-off-by: Bartosz Golaszewski Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240814122120.13975-1-brgl@bgdev.pl --- drivers/mtd/nand/raw/davinci_nand.c | 70 ++++++++++++++++++-- include/linux/platform_data/mtd-davinci-aemif.h | 36 ---------- include/linux/platform_data/mtd-davinci.h | 88 ------------------------- 3 files changed, 65 insertions(+), 129 deletions(-) delete mode 100644 include/linux/platform_data/mtd-davinci-aemif.h delete mode 100644 include/linux/platform_data/mtd-davinci.h (limited to 'include/linux/platform_data') diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index 051deea768db..392678143a36 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -20,8 +20,71 @@ #include #include -#include -#include +#define NRCSR_OFFSET 0x00 +#define NANDFCR_OFFSET 0x60 +#define NANDFSR_OFFSET 0x64 +#define NANDF1ECC_OFFSET 0x70 + +/* 4-bit ECC syndrome registers */ +#define NAND_4BIT_ECC_LOAD_OFFSET 0xbc +#define NAND_4BIT_ECC1_OFFSET 0xc0 +#define NAND_4BIT_ECC2_OFFSET 0xc4 +#define NAND_4BIT_ECC3_OFFSET 0xc8 +#define NAND_4BIT_ECC4_OFFSET 0xcc +#define NAND_ERR_ADD1_OFFSET 0xd0 +#define NAND_ERR_ADD2_OFFSET 0xd4 +#define NAND_ERR_ERRVAL1_OFFSET 0xd8 +#define NAND_ERR_ERRVAL2_OFFSET 0xdc + +/* NOTE: boards don't need to use these address bits + * for ALE/CLE unless they support booting from NAND. + * They're used unless platform data overrides them. + */ +#define MASK_ALE 0x08 +#define MASK_CLE 0x10 + +struct davinci_nand_pdata { + uint32_t mask_ale; + uint32_t mask_cle; + + /* + * 0-indexed chip-select number of the asynchronous + * interface to which the NAND device has been connected. + * + * So, if you have NAND connected to CS3 of DA850, you + * will pass '1' here. Since the asynchronous interface + * on DA850 starts from CS2. + */ + uint32_t core_chipsel; + + /* for packages using two chipselects */ + uint32_t mask_chipsel; + + /* board's default static partition info */ + struct mtd_partition *parts; + unsigned int nr_parts; + + /* none == NAND_ECC_ENGINE_TYPE_NONE (strongly *not* advised!!) + * soft == NAND_ECC_ENGINE_TYPE_SOFT + * else == NAND_ECC_ENGINE_TYPE_ON_HOST, according to ecc_bits + * + * All DaVinci-family chips support 1-bit hardware ECC. + * Newer ones also support 4-bit ECC, but are awkward + * using it with large page chips. + */ + enum nand_ecc_engine_type engine_type; + enum nand_ecc_placement ecc_placement; + u8 ecc_bits; + + /* e.g. NAND_BUSWIDTH_16 */ + unsigned int options; + /* e.g. NAND_BBT_USE_FLASH */ + unsigned int bbt_options; + + /* Main and mirror bbt descriptor overrides */ + struct nand_bbt_descr *bbt_td; + struct nand_bbt_descr *bbt_md; +}; /* * This is a device driver for the NAND flash controller found on the @@ -54,8 +117,6 @@ struct davinci_nand_info { uint32_t mask_cle; uint32_t core_chipsel; - - struct davinci_aemif_timing *timing; }; static DEFINE_SPINLOCK(davinci_nand_lock); @@ -775,7 +836,6 @@ static int nand_davinci_probe(struct platform_device *pdev) info->chip.options = pdata->options; info->chip.bbt_td = pdata->bbt_td; info->chip.bbt_md = pdata->bbt_md; - info->timing = pdata->timing; info->current_cs = info->vaddr; info->core_chipsel = pdata->core_chipsel; diff --git a/include/linux/platform_data/mtd-davinci-aemif.h b/include/linux/platform_data/mtd-davinci-aemif.h deleted file mode 100644 index a49826214a39..000000000000 --- a/include/linux/platform_data/mtd-davinci-aemif.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * TI DaVinci AEMIF support - * - * Copyright 2010 (C) Texas Instruments, Inc. https://www.ti.com/ - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ -#ifndef _MACH_DAVINCI_AEMIF_H -#define _MACH_DAVINCI_AEMIF_H - -#include - -#define NRCSR_OFFSET 0x00 -#define AWCCR_OFFSET 0x04 -#define A1CR_OFFSET 0x10 - -#define ACR_ASIZE_MASK 0x3 -#define ACR_EW_MASK BIT(30) -#define ACR_SS_MASK BIT(31) - -/* All timings in nanoseconds */ -struct davinci_aemif_timing { - u8 wsetup; - u8 wstrobe; - u8 whold; - - u8 rsetup; - u8 rstrobe; - u8 rhold; - - u8 ta; -}; - -#endif diff --git a/include/linux/platform_data/mtd-davinci.h b/include/linux/platform_data/mtd-davinci.h deleted file mode 100644 index dd474dd44848..000000000000 --- a/include/linux/platform_data/mtd-davinci.h +++ /dev/null @@ -1,88 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * mach-davinci/nand.h - * - * Copyright © 2006 Texas Instruments. - * - * Ported to 2.6.23 Copyright © 2008 by - * Sander Huijsen - * Troy Kisky - * Dirk Behme - * - * -------------------------------------------------------------------------- - */ - -#ifndef __ARCH_ARM_DAVINCI_NAND_H -#define __ARCH_ARM_DAVINCI_NAND_H - -#include - -#define NANDFCR_OFFSET 0x60 -#define NANDFSR_OFFSET 0x64 -#define NANDF1ECC_OFFSET 0x70 - -/* 4-bit ECC syndrome registers */ -#define NAND_4BIT_ECC_LOAD_OFFSET 0xbc -#define NAND_4BIT_ECC1_OFFSET 0xc0 -#define NAND_4BIT_ECC2_OFFSET 0xc4 -#define NAND_4BIT_ECC3_OFFSET 0xc8 -#define NAND_4BIT_ECC4_OFFSET 0xcc -#define NAND_ERR_ADD1_OFFSET 0xd0 -#define NAND_ERR_ADD2_OFFSET 0xd4 -#define NAND_ERR_ERRVAL1_OFFSET 0xd8 -#define NAND_ERR_ERRVAL2_OFFSET 0xdc - -/* NOTE: boards don't need to use these address bits - * for ALE/CLE unless they support booting from NAND. - * They're used unless platform data overrides them. - */ -#define MASK_ALE 0x08 -#define MASK_CLE 0x10 - -struct davinci_nand_pdata { /* platform_data */ - uint32_t mask_ale; - uint32_t mask_cle; - - /* - * 0-indexed chip-select number of the asynchronous - * interface to which the NAND device has been connected. - * - * So, if you have NAND connected to CS3 of DA850, you - * will pass '1' here. Since the asynchronous interface - * on DA850 starts from CS2. - */ - uint32_t core_chipsel; - - /* for packages using two chipselects */ - uint32_t mask_chipsel; - - /* board's default static partition info */ - struct mtd_partition *parts; - unsigned nr_parts; - - /* none == NAND_ECC_ENGINE_TYPE_NONE (strongly *not* advised!!) - * soft == NAND_ECC_ENGINE_TYPE_SOFT - * else == NAND_ECC_ENGINE_TYPE_ON_HOST, according to ecc_bits - * - * All DaVinci-family chips support 1-bit hardware ECC. - * Newer ones also support 4-bit ECC, but are awkward - * using it with large page chips. - */ - enum nand_ecc_engine_type engine_type; - enum nand_ecc_placement ecc_placement; - u8 ecc_bits; - - /* e.g. NAND_BUSWIDTH_16 */ - unsigned options; - /* e.g. NAND_BBT_USE_FLASH */ - unsigned bbt_options; - - /* Main and mirror bbt descriptor overrides */ - struct nand_bbt_descr *bbt_td; - struct nand_bbt_descr *bbt_md; - - /* Access timings */ - struct davinci_aemif_timing *timing; -}; - -#endif /* __ARCH_ARM_DAVINCI_NAND_H */ -- cgit v1.2.3 From a96c5515d0d15df103598b2bc57245d66143b5dd Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Mon, 26 Aug 2024 21:43:08 +0000 Subject: net: dsa: microchip: Add KSZ8895/KSZ8864 switch support KSZ8895/KSZ8864 is a switch family between KSZ8863/73 and KSZ8795, so it shares some registers and functions in those switches already implemented in the KSZ DSA driver. Signed-off-by: Tristram Ha Tested-by: Pieter Van Trappen Reviewed-by: Oleksij Rempel Signed-off-by: Jakub Kicinski --- drivers/net/dsa/microchip/ksz8795.c | 16 ++-- drivers/net/dsa/microchip/ksz_common.c | 134 ++++++++++++++++++++++++++-- drivers/net/dsa/microchip/ksz_common.h | 25 +++++- drivers/net/dsa/microchip/ksz_dcb.c | 2 +- drivers/net/dsa/microchip/ksz_spi.c | 15 +++- include/linux/platform_data/microchip-ksz.h | 2 + 6 files changed, 178 insertions(+), 16 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index a01079297a8c..aa09d89debf0 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -188,6 +188,8 @@ int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu) case KSZ8765_CHIP_ID: return ksz8795_change_mtu(dev, frame_size); case KSZ8830_CHIP_ID: + case KSZ8864_CHIP_ID: + case KSZ8895_CHIP_ID: return ksz8863_change_mtu(dev, frame_size); } @@ -384,7 +386,7 @@ static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, u64 *dropped, u64 *cnt) { - if (ksz_is_ksz88x3(dev)) + if (is_ksz88xx(dev)) ksz8863_r_mib_pkt(dev, port, addr, dropped, cnt); else ksz8795_r_mib_pkt(dev, port, addr, dropped, cnt); @@ -392,7 +394,7 @@ void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze) { - if (ksz_is_ksz88x3(dev)) + if (is_ksz88xx(dev)) return; /* enable the port for flush/freeze function */ @@ -410,7 +412,8 @@ void ksz8_port_init_cnt(struct ksz_device *dev, int port) struct ksz_port_mib *mib = &dev->ports[port].mib; u64 *dropped; - if (!ksz_is_ksz88x3(dev)) { + /* For KSZ8795 family. */ + if (ksz_is_ksz87xx(dev)) { /* flush all enabled port MIB counters */ ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true); ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FLUSH, true); @@ -609,11 +612,11 @@ static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr, shifts[STATIC_MAC_FWD_PORTS]; alu->is_override = (data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0; - /* KSZ8795 family switches have STATIC_MAC_TABLE_USE_FID and + /* KSZ8795/KSZ8895 family switches have STATIC_MAC_TABLE_USE_FID and * STATIC_MAC_TABLE_FID definitions off by 1 when doing read on the * static MAC table compared to doing write. */ - if (ksz_is_ksz87xx(dev)) + if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev)) data_hi >>= 1; alu->is_static = true; alu->is_use_fid = (data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0; @@ -1692,7 +1695,8 @@ void ksz8_config_cpu_port(struct dsa_switch *ds) for (i = 0; i < dev->phy_port_cnt; i++) { p = &dev->ports[i]; - if (!ksz_is_ksz88x3(dev)) { + /* For KSZ8795 family. */ + if (ksz_is_ksz87xx(dev)) { ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote); if (remote & KSZ8_PORT_FIBER_MODE) p->fiber = 1; diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index cd3991792b69..6609bf271ad0 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -2,7 +2,7 @@ /* * Microchip switch driver main logic * - * Copyright (C) 2017-2019 Microchip Technology Inc. + * Copyright (C) 2017-2024 Microchip Technology Inc. */ #include @@ -277,7 +277,7 @@ static const struct phylink_mac_ops ksz8_phylink_mac_ops = { .mac_link_up = ksz8_phylink_mac_link_up, }; -static const struct ksz_dev_ops ksz88x3_dev_ops = { +static const struct ksz_dev_ops ksz88xx_dev_ops = { .setup = ksz8_setup, .get_port_addr = ksz8_get_port_addr, .cfg_port_member = ksz8_cfg_port_member, @@ -572,6 +572,61 @@ static u8 ksz8863_shifts[] = { [DYNAMIC_MAC_SRC_PORT] = 20, }; +static const u16 ksz8895_regs[] = { + [REG_SW_MAC_ADDR] = 0x68, + [REG_IND_CTRL_0] = 0x6E, + [REG_IND_DATA_8] = 0x70, + [REG_IND_DATA_CHECK] = 0x72, + [REG_IND_DATA_HI] = 0x71, + [REG_IND_DATA_LO] = 0x75, + [REG_IND_MIB_CHECK] = 0x75, + [P_FORCE_CTRL] = 0x0C, + [P_LINK_STATUS] = 0x0E, + [P_LOCAL_CTRL] = 0x0C, + [P_NEG_RESTART_CTRL] = 0x0D, + [P_REMOTE_STATUS] = 0x0E, + [P_SPEED_STATUS] = 0x09, + [S_TAIL_TAG_CTRL] = 0x0C, + [P_STP_CTRL] = 0x02, + [S_START_CTRL] = 0x01, + [S_BROADCAST_CTRL] = 0x06, + [S_MULTICAST_CTRL] = 0x04, +}; + +static const u32 ksz8895_masks[] = { + [PORT_802_1P_REMAPPING] = BIT(7), + [SW_TAIL_TAG_ENABLE] = BIT(1), + [MIB_COUNTER_OVERFLOW] = BIT(7), + [MIB_COUNTER_VALID] = BIT(6), + [VLAN_TABLE_FID] = GENMASK(6, 0), + [VLAN_TABLE_MEMBERSHIP] = GENMASK(11, 7), + [VLAN_TABLE_VALID] = BIT(12), + [STATIC_MAC_TABLE_VALID] = BIT(21), + [STATIC_MAC_TABLE_USE_FID] = BIT(23), + [STATIC_MAC_TABLE_FID] = GENMASK(30, 24), + [STATIC_MAC_TABLE_OVERRIDE] = BIT(22), + [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(20, 16), + [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0), + [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7), + [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), + [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29), + [DYNAMIC_MAC_TABLE_FID] = GENMASK(22, 16), + [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24), + [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27), +}; + +static const u8 ksz8895_shifts[] = { + [VLAN_TABLE_MEMBERSHIP_S] = 7, + [VLAN_TABLE] = 13, + [STATIC_MAC_FWD_PORTS] = 16, + [STATIC_MAC_FID] = 24, + [DYNAMIC_MAC_ENTRIES_H] = 3, + [DYNAMIC_MAC_ENTRIES] = 29, + [DYNAMIC_MAC_FID] = 16, + [DYNAMIC_MAC_TIMESTAMP] = 27, + [DYNAMIC_MAC_SRC_PORT] = 24, +}; + static const u16 ksz9477_regs[] = { [REG_SW_MAC_ADDR] = 0x0302, [P_STP_CTRL] = 0x0B04, @@ -1397,7 +1452,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .port_cnt = 3, .num_tx_queues = 4, .num_ipms = 4, - .ops = &ksz88x3_dev_ops, + .ops = &ksz88xx_dev_ops, .phylink_mac_ops = &ksz8830_phylink_mac_ops, .mib_names = ksz88xx_mib_names, .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), @@ -1412,6 +1467,61 @@ const struct ksz_chip_data ksz_switch_chips[] = { .rd_table = &ksz8873_register_set, }, + [KSZ8864] = { + /* WARNING + * ======= + * KSZ8864 is similar to KSZ8895, except the first port + * does not exist. + * external cpu + * KSZ8864 1,2,3 4 + * KSZ8895 0,1,2,3 4 + * port_cnt is configured as 5, even though it is 4 + */ + .chip_id = KSZ8864_CHIP_ID, + .dev_name = "KSZ8864", + .num_vlans = 4096, + .num_alus = 0, + .num_statics = 32, + .cpu_ports = 0x10, /* can be configured as cpu port */ + .port_cnt = 5, /* total cpu and user ports */ + .num_tx_queues = 4, + .num_ipms = 4, + .ops = &ksz88xx_dev_ops, + .phylink_mac_ops = &ksz8830_phylink_mac_ops, + .mib_names = ksz88xx_mib_names, + .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), + .reg_mib_cnt = MIB_COUNTER_NUM, + .regs = ksz8895_regs, + .masks = ksz8895_masks, + .shifts = ksz8895_shifts, + .supports_mii = {false, false, false, false, true}, + .supports_rmii = {false, false, false, false, true}, + .internal_phy = {false, true, true, true, false}, + }, + + [KSZ8895] = { + .chip_id = KSZ8895_CHIP_ID, + .dev_name = "KSZ8895", + .num_vlans = 4096, + .num_alus = 0, + .num_statics = 32, + .cpu_ports = 0x10, /* can be configured as cpu port */ + .port_cnt = 5, /* total cpu and user ports */ + .num_tx_queues = 4, + .num_ipms = 4, + .ops = &ksz88xx_dev_ops, + .phylink_mac_ops = &ksz8830_phylink_mac_ops, + .mib_names = ksz88xx_mib_names, + .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), + .reg_mib_cnt = MIB_COUNTER_NUM, + .regs = ksz8895_regs, + .masks = ksz8895_masks, + .shifts = ksz8895_shifts, + .supports_mii = {false, false, false, false, true}, + .supports_rmii = {false, false, false, false, true}, + .internal_phy = {true, true, true, true, false}, + }, + [KSZ9477] = { .chip_id = KSZ9477_CHIP_ID, .dev_name = "KSZ9477", @@ -2937,9 +3047,7 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds, struct ksz_device *dev = ds->priv; enum dsa_tag_protocol proto = DSA_TAG_PROTO_NONE; - if (dev->chip_id == KSZ8795_CHIP_ID || - dev->chip_id == KSZ8794_CHIP_ID || - dev->chip_id == KSZ8765_CHIP_ID) + if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev)) proto = DSA_TAG_PROTO_KSZ8795; if (dev->chip_id == KSZ8830_CHIP_ID || @@ -3055,6 +3163,8 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port) case KSZ8765_CHIP_ID: return KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; case KSZ8830_CHIP_ID: + case KSZ8864_CHIP_ID: + case KSZ8895_CHIP_ID: return KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; case KSZ8563_CHIP_ID: case KSZ8567_CHIP_ID: @@ -3412,6 +3522,18 @@ static int ksz_switch_detect(struct ksz_device *dev) else return -ENODEV; break; + case KSZ8895_FAMILY_ID: + if (id2 == KSZ8895_CHIP_ID_95 || + id2 == KSZ8895_CHIP_ID_95R) + dev->chip_id = KSZ8895_CHIP_ID; + else + return -ENODEV; + ret = ksz_read8(dev, REG_KSZ8864_CHIP_ID, &id4); + if (ret) + return ret; + if (id4 & SW_KSZ8864) + dev->chip_id = KSZ8864_CHIP_ID; + break; default: ret = ksz_read32(dev, REG_CHIP_ID0, &id32); if (ret) diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 8094d90d6ca4..e08d5a1339f4 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Microchip switch driver common header * - * Copyright (C) 2017-2019 Microchip Technology Inc. + * Copyright (C) 2017-2024 Microchip Technology Inc. */ #ifndef __KSZ_COMMON_H @@ -201,6 +201,8 @@ enum ksz_model { KSZ8794, KSZ8765, KSZ8830, + KSZ8864, + KSZ8895, KSZ9477, KSZ9896, KSZ9897, @@ -629,9 +631,21 @@ static inline bool ksz_is_ksz88x3(struct ksz_device *dev) return dev->chip_id == KSZ8830_CHIP_ID; } +static inline bool ksz_is_8895_family(struct ksz_device *dev) +{ + return dev->chip_id == KSZ8895_CHIP_ID || + dev->chip_id == KSZ8864_CHIP_ID; +} + static inline bool is_ksz8(struct ksz_device *dev) { - return ksz_is_ksz87xx(dev) || ksz_is_ksz88x3(dev); + return ksz_is_ksz87xx(dev) || ksz_is_ksz88x3(dev) || + ksz_is_8895_family(dev); +} + +static inline bool is_ksz88xx(struct ksz_device *dev) +{ + return ksz_is_ksz88x3(dev) || ksz_is_8895_family(dev); } static inline bool is_ksz9477(struct ksz_device *dev) @@ -665,6 +679,7 @@ static inline bool is_lan937x_tx_phy(struct ksz_device *dev, int port) #define SW_FAMILY_ID_M GENMASK(15, 8) #define KSZ87_FAMILY_ID 0x87 #define KSZ88_FAMILY_ID 0x88 +#define KSZ8895_FAMILY_ID 0x95 #define KSZ8_PORT_STATUS_0 0x08 #define KSZ8_PORT_FIBER_MODE BIT(7) @@ -673,6 +688,12 @@ static inline bool is_lan937x_tx_phy(struct ksz_device *dev, int port) #define KSZ87_CHIP_ID_94 0x6 #define KSZ87_CHIP_ID_95 0x9 #define KSZ88_CHIP_ID_63 0x3 +#define KSZ8895_CHIP_ID_95 0x4 +#define KSZ8895_CHIP_ID_95R 0x6 + +/* KSZ8895 specific register */ +#define REG_KSZ8864_CHIP_ID 0xFE +#define SW_KSZ8864 BIT(7) #define SW_REV_ID_M GENMASK(7, 4) diff --git a/drivers/net/dsa/microchip/ksz_dcb.c b/drivers/net/dsa/microchip/ksz_dcb.c index 086bc9b3cf53..30b4a6186e38 100644 --- a/drivers/net/dsa/microchip/ksz_dcb.c +++ b/drivers/net/dsa/microchip/ksz_dcb.c @@ -113,7 +113,7 @@ static void ksz_get_default_port_prio_reg(struct ksz_device *dev, int *reg, static void ksz_get_dscp_prio_reg(struct ksz_device *dev, int *reg, int *per_reg, u8 *mask) { - if (ksz_is_ksz87xx(dev)) { + if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev)) { *reg = KSZ8765_REG_TOS_DSCP_CTRL; *per_reg = 4; *mask = GENMASK(1, 0); diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c index 8e8d83213b04..f4287310e89f 100644 --- a/drivers/net/dsa/microchip/ksz_spi.c +++ b/drivers/net/dsa/microchip/ksz_spi.c @@ -2,7 +2,7 @@ /* * Microchip ksz series register access through SPI * - * Copyright (C) 2017 Microchip Technology Inc. + * Copyright (C) 2017-2024 Microchip Technology Inc. * Tristram Ha */ @@ -60,6 +60,9 @@ static int ksz_spi_probe(struct spi_device *spi) chip->chip_id == KSZ8794_CHIP_ID || chip->chip_id == KSZ8765_CHIP_ID) regmap_config = ksz8795_regmap_config; + else if (chip->chip_id == KSZ8895_CHIP_ID || + chip->chip_id == KSZ8864_CHIP_ID) + regmap_config = ksz8863_regmap_config; else regmap_config = ksz9477_regmap_config; @@ -136,10 +139,18 @@ static const struct of_device_id ksz_dt_ids[] = { .compatible = "microchip,ksz8863", .data = &ksz_switch_chips[KSZ8830] }, + { + .compatible = "microchip,ksz8864", + .data = &ksz_switch_chips[KSZ8864] + }, { .compatible = "microchip,ksz8873", .data = &ksz_switch_chips[KSZ8830] }, + { + .compatible = "microchip,ksz8895", + .data = &ksz_switch_chips[KSZ8895] + }, { .compatible = "microchip,ksz9477", .data = &ksz_switch_chips[KSZ9477] @@ -201,7 +212,9 @@ static const struct spi_device_id ksz_spi_ids[] = { { "ksz8794" }, { "ksz8795" }, { "ksz8863" }, + { "ksz8864" }, { "ksz8873" }, + { "ksz8895" }, { "ksz9477" }, { "ksz9896" }, { "ksz9897" }, diff --git a/include/linux/platform_data/microchip-ksz.h b/include/linux/platform_data/microchip-ksz.h index 8c659db4da6b..d074019474f5 100644 --- a/include/linux/platform_data/microchip-ksz.h +++ b/include/linux/platform_data/microchip-ksz.h @@ -28,6 +28,8 @@ enum ksz_chip_id { KSZ8794_CHIP_ID = 0x8794, KSZ8765_CHIP_ID = 0x8765, KSZ8830_CHIP_ID = 0x8830, + KSZ8864_CHIP_ID = 0x8864, + KSZ8895_CHIP_ID = 0x8895, KSZ9477_CHIP_ID = 0x00947700, KSZ9896_CHIP_ID = 0x00989600, KSZ9897_CHIP_ID = 0x00989700, -- cgit v1.2.3 From 73d5fc92a11cacb73a1aac0b5793c47e48c5b537 Mon Sep 17 00:00:00 2001 From: Nishad Saraf Date: Mon, 19 Aug 2024 14:19:48 -0700 Subject: dmaengine: amd: qdma: Add AMD QDMA driver Adds driver to enable PCIe board which uses AMD QDMA (the Queue-based Direct Memory Access) subsystem. For example, Xilinx Alveo V70 AI Accelerator devices. https://www.xilinx.com/applications/data-center/v70.html The QDMA subsystem is used in conjunction with the PCI Express IP block to provide high performance data transfer between host memory and the card's DMA subsystem. +-------+ +-------+ +-----------+ PCIe | | | | | | Tx/Rx | | | | AXI | | <=======> | PCIE | <===> | QDMA | <====>| User Logic| | | | | | | +-------+ +-------+ +-----------+ The primary mechanism to transfer data using the QDMA is for the QDMA engine to operate on instructions (descriptors) provided by the host operating system. Using the descriptors, the QDMA can move data in both the Host to Card (H2C) direction, or the Card to Host (C2H) direction. The QDMA provides a per-queue basis option whether DMA traffic goes to an AXI4 memory map (MM) interface or to an AXI4-Stream interface. The hardware detail is provided by https://docs.xilinx.com/r/en-US/pg302-qdma Implements dmaengine APIs to support MM DMA transfers. - probe the available DMA channels - use dma_slave_map for channel lookup - use virtual channel to manage dmaengine tx descriptors - implement device_prep_slave_sg callback to handle host scatter gather list Signed-off-by: Nishad Saraf Signed-off-by: Lizhi Hou Link: https://lore.kernel.org/r/20240819211948.688786-2-lizhi.hou@amd.com Signed-off-by: Vinod Koul --- MAINTAINERS | 8 + drivers/dma/Kconfig | 2 + drivers/dma/Makefile | 1 + drivers/dma/amd/Kconfig | 14 + drivers/dma/amd/Makefile | 3 + drivers/dma/amd/qdma/Makefile | 5 + drivers/dma/amd/qdma/qdma-comm-regs.c | 64 ++ drivers/dma/amd/qdma/qdma.c | 1143 ++++++++++++++++++++++++++++++++ drivers/dma/amd/qdma/qdma.h | 266 ++++++++ include/linux/platform_data/amd_qdma.h | 36 + 10 files changed, 1542 insertions(+) create mode 100644 drivers/dma/amd/Kconfig create mode 100644 drivers/dma/amd/Makefile create mode 100644 drivers/dma/amd/qdma/Makefile create mode 100644 drivers/dma/amd/qdma/qdma-comm-regs.c create mode 100644 drivers/dma/amd/qdma/qdma.c create mode 100644 drivers/dma/amd/qdma/qdma.h create mode 100644 include/linux/platform_data/amd_qdma.h (limited to 'include/linux/platform_data') diff --git a/MAINTAINERS b/MAINTAINERS index 42decde38320..a9154c66795b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1128,6 +1128,14 @@ L: dmaengine@vger.kernel.org S: Maintained F: drivers/dma/ptdma/ +AMD QDMA DRIVER +M: Nishad Saraf +M: Lizhi Hou +L: dmaengine@vger.kernel.org +S: Supported +F: drivers/dma/amd/qdma/ +F: include/linux/platform_data/amd_qdma.h + AMD SEATTLE DEVICE TREE SUPPORT M: Suravee Suthikulpanit M: Tom Lendacky diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index cc0a62c34861..dbb75d35d767 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -716,6 +716,8 @@ config XILINX_ZYNQMP_DPDMA display driver. # driver files +source "drivers/dma/amd/Kconfig" + source "drivers/dma/bestcomm/Kconfig" source "drivers/dma/mediatek/Kconfig" diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 374ea98faf43..29c99bf9fd37 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -83,6 +83,7 @@ obj-$(CONFIG_ST_FDMA) += st_fdma.o obj-$(CONFIG_FSL_DPAA2_QDMA) += fsl-dpaa2-qdma/ obj-$(CONFIG_INTEL_LDMA) += lgm/ +obj-y += amd/ obj-y += mediatek/ obj-y += qcom/ obj-y += stm32/ diff --git a/drivers/dma/amd/Kconfig b/drivers/dma/amd/Kconfig new file mode 100644 index 000000000000..7d1f51d69675 --- /dev/null +++ b/drivers/dma/amd/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config AMD_QDMA + tristate "AMD Queue-based DMA" + depends on HAS_IOMEM + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + select REGMAP_MMIO + help + Enable support for the AMD Queue-based DMA subsystem. The primary + mechanism to transfer data using the QDMA is for the QDMA engine to + operate on instructions (descriptors) provided by the host operating + system. Using the descriptors, the QDMA can move data in either the + Host to Card (H2C) direction or the Card to Host (C2H) direction. diff --git a/drivers/dma/amd/Makefile b/drivers/dma/amd/Makefile new file mode 100644 index 000000000000..37212be9364f --- /dev/null +++ b/drivers/dma/amd/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_AMD_QDMA) += qdma/ diff --git a/drivers/dma/amd/qdma/Makefile b/drivers/dma/amd/qdma/Makefile new file mode 100644 index 000000000000..011268fef377 --- /dev/null +++ b/drivers/dma/amd/qdma/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_AMD_QDMA) += amd-qdma.o + +amd-qdma-$(CONFIG_AMD_QDMA) := qdma.o qdma-comm-regs.o diff --git a/drivers/dma/amd/qdma/qdma-comm-regs.c b/drivers/dma/amd/qdma/qdma-comm-regs.c new file mode 100644 index 000000000000..9162f9d367cc --- /dev/null +++ b/drivers/dma/amd/qdma/qdma-comm-regs.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023-2024, Advanced Micro Devices, Inc. + */ + +#ifndef __QDMA_REGS_DEF_H +#define __QDMA_REGS_DEF_H + +#include "qdma.h" + +const struct qdma_reg qdma_regos_default[QDMA_REGO_MAX] = { + [QDMA_REGO_CTXT_DATA] = QDMA_REGO(0x804, 8), + [QDMA_REGO_CTXT_CMD] = QDMA_REGO(0x844, 1), + [QDMA_REGO_CTXT_MASK] = QDMA_REGO(0x824, 8), + [QDMA_REGO_MM_H2C_CTRL] = QDMA_REGO(0x1004, 1), + [QDMA_REGO_MM_C2H_CTRL] = QDMA_REGO(0x1204, 1), + [QDMA_REGO_QUEUE_COUNT] = QDMA_REGO(0x120, 1), + [QDMA_REGO_RING_SIZE] = QDMA_REGO(0x204, 1), + [QDMA_REGO_H2C_PIDX] = QDMA_REGO(0x18004, 1), + [QDMA_REGO_C2H_PIDX] = QDMA_REGO(0x18008, 1), + [QDMA_REGO_INTR_CIDX] = QDMA_REGO(0x18000, 1), + [QDMA_REGO_FUNC_ID] = QDMA_REGO(0x12c, 1), + [QDMA_REGO_ERR_INT] = QDMA_REGO(0xb04, 1), + [QDMA_REGO_ERR_STAT] = QDMA_REGO(0x248, 1), +}; + +const struct qdma_reg_field qdma_regfs_default[QDMA_REGF_MAX] = { + /* QDMA_REGO_CTXT_DATA fields */ + [QDMA_REGF_IRQ_ENABLE] = QDMA_REGF(53, 53), + [QDMA_REGF_WBK_ENABLE] = QDMA_REGF(52, 52), + [QDMA_REGF_WBI_CHECK] = QDMA_REGF(34, 34), + [QDMA_REGF_IRQ_ARM] = QDMA_REGF(16, 16), + [QDMA_REGF_IRQ_VEC] = QDMA_REGF(138, 128), + [QDMA_REGF_IRQ_AGG] = QDMA_REGF(139, 139), + [QDMA_REGF_WBI_INTVL_ENABLE] = QDMA_REGF(35, 35), + [QDMA_REGF_MRKR_DISABLE] = QDMA_REGF(62, 62), + [QDMA_REGF_QUEUE_ENABLE] = QDMA_REGF(32, 32), + [QDMA_REGF_QUEUE_MODE] = QDMA_REGF(63, 63), + [QDMA_REGF_DESC_BASE] = QDMA_REGF(127, 64), + [QDMA_REGF_DESC_SIZE] = QDMA_REGF(49, 48), + [QDMA_REGF_RING_ID] = QDMA_REGF(47, 44), + [QDMA_REGF_QUEUE_BASE] = QDMA_REGF(11, 0), + [QDMA_REGF_QUEUE_MAX] = QDMA_REGF(44, 32), + [QDMA_REGF_FUNCTION_ID] = QDMA_REGF(24, 17), + [QDMA_REGF_INTR_AGG_BASE] = QDMA_REGF(66, 15), + [QDMA_REGF_INTR_VECTOR] = QDMA_REGF(11, 1), + [QDMA_REGF_INTR_SIZE] = QDMA_REGF(69, 67), + [QDMA_REGF_INTR_VALID] = QDMA_REGF(0, 0), + [QDMA_REGF_INTR_COLOR] = QDMA_REGF(14, 14), + [QDMA_REGF_INTR_FUNCTION_ID] = QDMA_REGF(125, 114), + /* QDMA_REGO_CTXT_CMD fields */ + [QDMA_REGF_CMD_INDX] = QDMA_REGF(19, 7), + [QDMA_REGF_CMD_CMD] = QDMA_REGF(6, 5), + [QDMA_REGF_CMD_TYPE] = QDMA_REGF(4, 1), + [QDMA_REGF_CMD_BUSY] = QDMA_REGF(0, 0), + /* QDMA_REGO_QUEUE_COUNT fields */ + [QDMA_REGF_QUEUE_COUNT] = QDMA_REGF(11, 0), + /* QDMA_REGO_ERR_INT fields */ + [QDMA_REGF_ERR_INT_FUNC] = QDMA_REGF(11, 0), + [QDMA_REGF_ERR_INT_VEC] = QDMA_REGF(22, 12), + [QDMA_REGF_ERR_INT_ARM] = QDMA_REGF(24, 24), +}; + +#endif /* __QDMA_REGS_DEF_H */ diff --git a/drivers/dma/amd/qdma/qdma.c b/drivers/dma/amd/qdma/qdma.c new file mode 100644 index 000000000000..b0a1f3ad851b --- /dev/null +++ b/drivers/dma/amd/qdma/qdma.c @@ -0,0 +1,1143 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * DMA driver for AMD Queue-based DMA Subsystem + * + * Copyright (C) 2023-2024, Advanced Micro Devices, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qdma.h" + +#define CHAN_STR(q) (((q)->dir == DMA_MEM_TO_DEV) ? "H2C" : "C2H") +#define QDMA_REG_OFF(d, r) ((d)->roffs[r].off) + +/* MMIO regmap config for all QDMA registers */ +static const struct regmap_config qdma_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static inline struct qdma_queue *to_qdma_queue(struct dma_chan *chan) +{ + return container_of(chan, struct qdma_queue, vchan.chan); +} + +static inline struct qdma_mm_vdesc *to_qdma_vdesc(struct virt_dma_desc *vdesc) +{ + return container_of(vdesc, struct qdma_mm_vdesc, vdesc); +} + +static inline u32 qdma_get_intr_ring_idx(struct qdma_device *qdev) +{ + u32 idx; + + idx = qdev->qintr_rings[qdev->qintr_ring_idx++].ridx; + qdev->qintr_ring_idx %= qdev->qintr_ring_num; + + return idx; +} + +static u64 qdma_get_field(const struct qdma_device *qdev, const u32 *data, + enum qdma_reg_fields field) +{ + const struct qdma_reg_field *f = &qdev->rfields[field]; + u16 low_pos, hi_pos, low_bit, hi_bit; + u64 value = 0, mask; + + low_pos = f->lsb / BITS_PER_TYPE(*data); + hi_pos = f->msb / BITS_PER_TYPE(*data); + + if (low_pos == hi_pos) { + low_bit = f->lsb % BITS_PER_TYPE(*data); + hi_bit = f->msb % BITS_PER_TYPE(*data); + mask = GENMASK(hi_bit, low_bit); + value = (data[low_pos] & mask) >> low_bit; + } else if (hi_pos == low_pos + 1) { + low_bit = f->lsb % BITS_PER_TYPE(*data); + hi_bit = low_bit + (f->msb - f->lsb); + value = ((u64)data[hi_pos] << BITS_PER_TYPE(*data)) | + data[low_pos]; + mask = GENMASK_ULL(hi_bit, low_bit); + value = (value & mask) >> low_bit; + } else { + hi_bit = f->msb % BITS_PER_TYPE(*data); + mask = GENMASK(hi_bit, 0); + value = data[hi_pos] & mask; + low_bit = f->msb - f->lsb - hi_bit; + value <<= low_bit; + low_bit -= 32; + value |= (u64)data[hi_pos - 1] << low_bit; + mask = GENMASK(31, 32 - low_bit); + value |= (data[hi_pos - 2] & mask) >> low_bit; + } + + return value; +} + +static void qdma_set_field(const struct qdma_device *qdev, u32 *data, + enum qdma_reg_fields field, u64 value) +{ + const struct qdma_reg_field *f = &qdev->rfields[field]; + u16 low_pos, hi_pos, low_bit; + + low_pos = f->lsb / BITS_PER_TYPE(*data); + hi_pos = f->msb / BITS_PER_TYPE(*data); + low_bit = f->lsb % BITS_PER_TYPE(*data); + + data[low_pos++] |= value << low_bit; + if (low_pos <= hi_pos) + data[low_pos++] |= (u32)(value >> (32 - low_bit)); + if (low_pos <= hi_pos) + data[low_pos] |= (u32)(value >> (64 - low_bit)); +} + +static inline int qdma_reg_write(const struct qdma_device *qdev, + const u32 *data, enum qdma_regs reg) +{ + const struct qdma_reg *r = &qdev->roffs[reg]; + int ret; + + if (r->count > 1) + ret = regmap_bulk_write(qdev->regmap, r->off, data, r->count); + else + ret = regmap_write(qdev->regmap, r->off, *data); + + return ret; +} + +static inline int qdma_reg_read(const struct qdma_device *qdev, u32 *data, + enum qdma_regs reg) +{ + const struct qdma_reg *r = &qdev->roffs[reg]; + int ret; + + if (r->count > 1) + ret = regmap_bulk_read(qdev->regmap, r->off, data, r->count); + else + ret = regmap_read(qdev->regmap, r->off, data); + + return ret; +} + +static int qdma_context_cmd_execute(const struct qdma_device *qdev, + enum qdma_ctxt_type type, + enum qdma_ctxt_cmd cmd, u16 index) +{ + u32 value = 0; + int ret; + + qdma_set_field(qdev, &value, QDMA_REGF_CMD_INDX, index); + qdma_set_field(qdev, &value, QDMA_REGF_CMD_CMD, cmd); + qdma_set_field(qdev, &value, QDMA_REGF_CMD_TYPE, type); + + ret = qdma_reg_write(qdev, &value, QDMA_REGO_CTXT_CMD); + if (ret) + return ret; + + ret = regmap_read_poll_timeout(qdev->regmap, + QDMA_REG_OFF(qdev, QDMA_REGO_CTXT_CMD), + value, + !qdma_get_field(qdev, &value, + QDMA_REGF_CMD_BUSY), + QDMA_POLL_INTRVL_US, + QDMA_POLL_TIMEOUT_US); + if (ret) { + qdma_err(qdev, "Context command execution timed out"); + return ret; + } + + return 0; +} + +static int qdma_context_write_data(const struct qdma_device *qdev, + const u32 *data) +{ + u32 mask[QDMA_CTXT_REGMAP_LEN]; + int ret; + + memset(mask, ~0, sizeof(mask)); + + ret = qdma_reg_write(qdev, mask, QDMA_REGO_CTXT_MASK); + if (ret) + return ret; + + ret = qdma_reg_write(qdev, data, QDMA_REGO_CTXT_DATA); + if (ret) + return ret; + + return 0; +} + +static void qdma_prep_sw_desc_context(const struct qdma_device *qdev, + const struct qdma_ctxt_sw_desc *ctxt, + u32 *data) +{ + memset(data, 0, QDMA_CTXT_REGMAP_LEN * sizeof(*data)); + qdma_set_field(qdev, data, QDMA_REGF_DESC_BASE, ctxt->desc_base); + qdma_set_field(qdev, data, QDMA_REGF_IRQ_VEC, ctxt->vec); + qdma_set_field(qdev, data, QDMA_REGF_FUNCTION_ID, qdev->fid); + + qdma_set_field(qdev, data, QDMA_REGF_DESC_SIZE, QDMA_DESC_SIZE_32B); + qdma_set_field(qdev, data, QDMA_REGF_RING_ID, QDMA_DEFAULT_RING_ID); + qdma_set_field(qdev, data, QDMA_REGF_QUEUE_MODE, QDMA_QUEUE_OP_MM); + qdma_set_field(qdev, data, QDMA_REGF_IRQ_ENABLE, 1); + qdma_set_field(qdev, data, QDMA_REGF_WBK_ENABLE, 1); + qdma_set_field(qdev, data, QDMA_REGF_WBI_CHECK, 1); + qdma_set_field(qdev, data, QDMA_REGF_IRQ_ARM, 1); + qdma_set_field(qdev, data, QDMA_REGF_IRQ_AGG, 1); + qdma_set_field(qdev, data, QDMA_REGF_WBI_INTVL_ENABLE, 1); + qdma_set_field(qdev, data, QDMA_REGF_QUEUE_ENABLE, 1); + qdma_set_field(qdev, data, QDMA_REGF_MRKR_DISABLE, 1); +} + +static void qdma_prep_intr_context(const struct qdma_device *qdev, + const struct qdma_ctxt_intr *ctxt, + u32 *data) +{ + memset(data, 0, QDMA_CTXT_REGMAP_LEN * sizeof(*data)); + qdma_set_field(qdev, data, QDMA_REGF_INTR_AGG_BASE, ctxt->agg_base); + qdma_set_field(qdev, data, QDMA_REGF_INTR_VECTOR, ctxt->vec); + qdma_set_field(qdev, data, QDMA_REGF_INTR_SIZE, ctxt->size); + qdma_set_field(qdev, data, QDMA_REGF_INTR_VALID, ctxt->valid); + qdma_set_field(qdev, data, QDMA_REGF_INTR_COLOR, ctxt->color); + qdma_set_field(qdev, data, QDMA_REGF_INTR_FUNCTION_ID, qdev->fid); +} + +static void qdma_prep_fmap_context(const struct qdma_device *qdev, + const struct qdma_ctxt_fmap *ctxt, + u32 *data) +{ + memset(data, 0, QDMA_CTXT_REGMAP_LEN * sizeof(*data)); + qdma_set_field(qdev, data, QDMA_REGF_QUEUE_BASE, ctxt->qbase); + qdma_set_field(qdev, data, QDMA_REGF_QUEUE_MAX, ctxt->qmax); +} + +/* + * Program the indirect context register space + * + * Once the queue is enabled, context is dynamically updated by hardware. Any + * modification of the context through this API when the queue is enabled can + * result in unexpected behavior. Reading the context when the queue is enabled + * is not recommended as it can result in reduced performance. + */ +static int qdma_prog_context(struct qdma_device *qdev, enum qdma_ctxt_type type, + enum qdma_ctxt_cmd cmd, u16 index, u32 *ctxt) +{ + int ret; + + mutex_lock(&qdev->ctxt_lock); + if (cmd == QDMA_CTXT_WRITE) { + ret = qdma_context_write_data(qdev, ctxt); + if (ret) + goto failed; + } + + ret = qdma_context_cmd_execute(qdev, type, cmd, index); + if (ret) + goto failed; + + if (cmd == QDMA_CTXT_READ) { + ret = qdma_reg_read(qdev, ctxt, QDMA_REGO_CTXT_DATA); + if (ret) + goto failed; + } + +failed: + mutex_unlock(&qdev->ctxt_lock); + + return ret; +} + +static int qdma_check_queue_status(struct qdma_device *qdev, + enum dma_transfer_direction dir, u16 qid) +{ + u32 status, data[QDMA_CTXT_REGMAP_LEN] = {0}; + enum qdma_ctxt_type type; + int ret; + + if (dir == DMA_MEM_TO_DEV) + type = QDMA_CTXT_DESC_SW_H2C; + else + type = QDMA_CTXT_DESC_SW_C2H; + ret = qdma_prog_context(qdev, type, QDMA_CTXT_READ, qid, data); + if (ret) + return ret; + + status = qdma_get_field(qdev, data, QDMA_REGF_QUEUE_ENABLE); + if (status) { + qdma_err(qdev, "queue %d already in use", qid); + return -EBUSY; + } + + return 0; +} + +static int qdma_clear_queue_context(const struct qdma_queue *queue) +{ + enum qdma_ctxt_type h2c_types[] = { QDMA_CTXT_DESC_SW_H2C, + QDMA_CTXT_DESC_HW_H2C, + QDMA_CTXT_DESC_CR_H2C, + QDMA_CTXT_PFTCH, }; + enum qdma_ctxt_type c2h_types[] = { QDMA_CTXT_DESC_SW_C2H, + QDMA_CTXT_DESC_HW_C2H, + QDMA_CTXT_DESC_CR_C2H, + QDMA_CTXT_PFTCH, }; + struct qdma_device *qdev = queue->qdev; + enum qdma_ctxt_type *type; + int ret, num, i; + + if (queue->dir == DMA_MEM_TO_DEV) { + type = h2c_types; + num = ARRAY_SIZE(h2c_types); + } else { + type = c2h_types; + num = ARRAY_SIZE(c2h_types); + } + for (i = 0; i < num; i++) { + ret = qdma_prog_context(qdev, type[i], QDMA_CTXT_CLEAR, + queue->qid, NULL); + if (ret) { + qdma_err(qdev, "Failed to clear ctxt %d", type[i]); + return ret; + } + } + + return 0; +} + +static int qdma_setup_fmap_context(struct qdma_device *qdev) +{ + u32 ctxt[QDMA_CTXT_REGMAP_LEN]; + struct qdma_ctxt_fmap fmap; + int ret; + + ret = qdma_prog_context(qdev, QDMA_CTXT_FMAP, QDMA_CTXT_CLEAR, + qdev->fid, NULL); + if (ret) { + qdma_err(qdev, "Failed clearing context"); + return ret; + } + + fmap.qbase = 0; + fmap.qmax = qdev->chan_num * 2; + qdma_prep_fmap_context(qdev, &fmap, ctxt); + ret = qdma_prog_context(qdev, QDMA_CTXT_FMAP, QDMA_CTXT_WRITE, + qdev->fid, ctxt); + if (ret) + qdma_err(qdev, "Failed setup fmap, ret %d", ret); + + return ret; +} + +static int qdma_setup_queue_context(struct qdma_device *qdev, + const struct qdma_ctxt_sw_desc *sw_desc, + enum dma_transfer_direction dir, u16 qid) +{ + u32 ctxt[QDMA_CTXT_REGMAP_LEN]; + enum qdma_ctxt_type type; + int ret; + + if (dir == DMA_MEM_TO_DEV) + type = QDMA_CTXT_DESC_SW_H2C; + else + type = QDMA_CTXT_DESC_SW_C2H; + + qdma_prep_sw_desc_context(qdev, sw_desc, ctxt); + /* Setup SW descriptor context */ + ret = qdma_prog_context(qdev, type, QDMA_CTXT_WRITE, qid, ctxt); + if (ret) + qdma_err(qdev, "Failed setup SW desc ctxt for queue: %d", qid); + + return ret; +} + +/* + * Enable or disable memory-mapped DMA engines + * 1: enable, 0: disable + */ +static int qdma_sgdma_control(struct qdma_device *qdev, u32 ctrl) +{ + int ret; + + ret = qdma_reg_write(qdev, &ctrl, QDMA_REGO_MM_H2C_CTRL); + ret |= qdma_reg_write(qdev, &ctrl, QDMA_REGO_MM_C2H_CTRL); + + return ret; +} + +static int qdma_get_hw_info(struct qdma_device *qdev) +{ + struct qdma_platdata *pdata = dev_get_platdata(&qdev->pdev->dev); + u32 value = 0; + int ret; + + ret = qdma_reg_read(qdev, &value, QDMA_REGO_QUEUE_COUNT); + if (ret) + return ret; + + value = qdma_get_field(qdev, &value, QDMA_REGF_QUEUE_COUNT) + 1; + if (pdata->max_mm_channels * 2 > value) { + qdma_err(qdev, "not enough hw queues %d", value); + return -EINVAL; + } + qdev->chan_num = pdata->max_mm_channels; + + ret = qdma_reg_read(qdev, &qdev->fid, QDMA_REGO_FUNC_ID); + if (ret) + return ret; + + qdma_info(qdev, "max channel %d, function id %d", + qdev->chan_num, qdev->fid); + + return 0; +} + +static inline int qdma_update_pidx(const struct qdma_queue *queue, u16 pidx) +{ + struct qdma_device *qdev = queue->qdev; + + return regmap_write(qdev->regmap, queue->pidx_reg, + pidx | QDMA_QUEUE_ARM_BIT); +} + +static inline int qdma_update_cidx(const struct qdma_queue *queue, + u16 ridx, u16 cidx) +{ + struct qdma_device *qdev = queue->qdev; + + return regmap_write(qdev->regmap, queue->cidx_reg, + ((u32)ridx << 16) | cidx); +} + +/** + * qdma_free_vdesc - Free descriptor + * @vdesc: Virtual DMA descriptor + */ +static void qdma_free_vdesc(struct virt_dma_desc *vdesc) +{ + struct qdma_mm_vdesc *vd = to_qdma_vdesc(vdesc); + + kfree(vd); +} + +static int qdma_alloc_queues(struct qdma_device *qdev, + enum dma_transfer_direction dir) +{ + struct qdma_queue *q, **queues; + u32 i, pidx_base; + int ret; + + if (dir == DMA_MEM_TO_DEV) { + queues = &qdev->h2c_queues; + pidx_base = QDMA_REG_OFF(qdev, QDMA_REGO_H2C_PIDX); + } else { + queues = &qdev->c2h_queues; + pidx_base = QDMA_REG_OFF(qdev, QDMA_REGO_C2H_PIDX); + } + + *queues = devm_kcalloc(&qdev->pdev->dev, qdev->chan_num, sizeof(*q), + GFP_KERNEL); + if (!*queues) + return -ENOMEM; + + for (i = 0; i < qdev->chan_num; i++) { + ret = qdma_check_queue_status(qdev, dir, i); + if (ret) + return ret; + + q = &(*queues)[i]; + q->ring_size = QDMA_DEFAULT_RING_SIZE; + q->idx_mask = q->ring_size - 2; + q->qdev = qdev; + q->dir = dir; + q->qid = i; + q->pidx_reg = pidx_base + i * QDMA_DMAP_REG_STRIDE; + q->cidx_reg = QDMA_REG_OFF(qdev, QDMA_REGO_INTR_CIDX) + + i * QDMA_DMAP_REG_STRIDE; + q->vchan.desc_free = qdma_free_vdesc; + vchan_init(&q->vchan, &qdev->dma_dev); + } + + return 0; +} + +static int qdma_device_verify(struct qdma_device *qdev) +{ + u32 value; + int ret; + + ret = regmap_read(qdev->regmap, QDMA_IDENTIFIER_REGOFF, &value); + if (ret) + return ret; + + value = FIELD_GET(QDMA_IDENTIFIER_MASK, value); + if (value != QDMA_IDENTIFIER) { + qdma_err(qdev, "Invalid identifier"); + return -ENODEV; + } + qdev->rfields = qdma_regfs_default; + qdev->roffs = qdma_regos_default; + + return 0; +} + +static int qdma_device_setup(struct qdma_device *qdev) +{ + struct device *dev = &qdev->pdev->dev; + u32 ring_sz = QDMA_DEFAULT_RING_SIZE; + int ret = 0; + + while (dev && get_dma_ops(dev)) + dev = dev->parent; + if (!dev) { + qdma_err(qdev, "dma device not found"); + return -EINVAL; + } + set_dma_ops(&qdev->pdev->dev, get_dma_ops(dev)); + + ret = qdma_setup_fmap_context(qdev); + if (ret) { + qdma_err(qdev, "Failed setup fmap context"); + return ret; + } + + /* Setup global ring buffer size at QDMA_DEFAULT_RING_ID index */ + ret = qdma_reg_write(qdev, &ring_sz, QDMA_REGO_RING_SIZE); + if (ret) { + qdma_err(qdev, "Failed to setup ring %d of size %ld", + QDMA_DEFAULT_RING_ID, QDMA_DEFAULT_RING_SIZE); + return ret; + } + + /* Enable memory-mapped DMA engine in both directions */ + ret = qdma_sgdma_control(qdev, 1); + if (ret) { + qdma_err(qdev, "Failed to SGDMA with error %d", ret); + return ret; + } + + ret = qdma_alloc_queues(qdev, DMA_MEM_TO_DEV); + if (ret) { + qdma_err(qdev, "Failed to alloc H2C queues, ret %d", ret); + return ret; + } + + ret = qdma_alloc_queues(qdev, DMA_DEV_TO_MEM); + if (ret) { + qdma_err(qdev, "Failed to alloc C2H queues, ret %d", ret); + return ret; + } + + return 0; +} + +/** + * qdma_free_queue_resources() - Free queue resources + * @chan: DMA channel + */ +static void qdma_free_queue_resources(struct dma_chan *chan) +{ + struct qdma_queue *queue = to_qdma_queue(chan); + struct qdma_device *qdev = queue->qdev; + struct device *dev = qdev->dma_dev.dev; + + qdma_clear_queue_context(queue); + vchan_free_chan_resources(&queue->vchan); + dma_free_coherent(dev, queue->ring_size * QDMA_MM_DESC_SIZE, + queue->desc_base, queue->dma_desc_base); +} + +/** + * qdma_alloc_queue_resources() - Allocate queue resources + * @chan: DMA channel + */ +static int qdma_alloc_queue_resources(struct dma_chan *chan) +{ + struct qdma_queue *queue = to_qdma_queue(chan); + struct qdma_device *qdev = queue->qdev; + struct qdma_ctxt_sw_desc desc; + size_t size; + int ret; + + ret = qdma_clear_queue_context(queue); + if (ret) + return ret; + + size = queue->ring_size * QDMA_MM_DESC_SIZE; + queue->desc_base = dma_alloc_coherent(qdev->dma_dev.dev, size, + &queue->dma_desc_base, + GFP_KERNEL); + if (!queue->desc_base) { + qdma_err(qdev, "Failed to allocate descriptor ring"); + return -ENOMEM; + } + + /* Setup SW descriptor queue context for DMA memory map */ + desc.vec = qdma_get_intr_ring_idx(qdev); + desc.desc_base = queue->dma_desc_base; + ret = qdma_setup_queue_context(qdev, &desc, queue->dir, queue->qid); + if (ret) { + qdma_err(qdev, "Failed to setup SW desc ctxt for %s", + chan->name); + dma_free_coherent(qdev->dma_dev.dev, size, queue->desc_base, + queue->dma_desc_base); + return ret; + } + + queue->pidx = 0; + queue->cidx = 0; + + return 0; +} + +static bool qdma_filter_fn(struct dma_chan *chan, void *param) +{ + struct qdma_queue *queue = to_qdma_queue(chan); + struct qdma_queue_info *info = param; + + return info->dir == queue->dir; +} + +static int qdma_xfer_start(struct qdma_queue *queue) +{ + struct qdma_device *qdev = queue->qdev; + int ret; + + if (!vchan_next_desc(&queue->vchan)) + return 0; + + qdma_dbg(qdev, "Tnx kickoff with P: %d for %s%d", + queue->issued_vdesc->pidx, CHAN_STR(queue), queue->qid); + + ret = qdma_update_pidx(queue, queue->issued_vdesc->pidx); + if (ret) { + qdma_err(qdev, "Failed to update PIDX to %d for %s queue: %d", + queue->pidx, CHAN_STR(queue), queue->qid); + } + + return ret; +} + +static void qdma_issue_pending(struct dma_chan *chan) +{ + struct qdma_queue *queue = to_qdma_queue(chan); + unsigned long flags; + + spin_lock_irqsave(&queue->vchan.lock, flags); + if (vchan_issue_pending(&queue->vchan)) { + if (queue->submitted_vdesc) { + queue->issued_vdesc = queue->submitted_vdesc; + queue->submitted_vdesc = NULL; + } + qdma_xfer_start(queue); + } + + spin_unlock_irqrestore(&queue->vchan.lock, flags); +} + +static struct qdma_mm_desc *qdma_get_desc(struct qdma_queue *q) +{ + struct qdma_mm_desc *desc; + + if (((q->pidx + 1) & q->idx_mask) == q->cidx) + return NULL; + + desc = q->desc_base + q->pidx; + q->pidx = (q->pidx + 1) & q->idx_mask; + + return desc; +} + +static int qdma_hw_enqueue(struct qdma_queue *q, struct qdma_mm_vdesc *vdesc) +{ + struct qdma_mm_desc *desc; + struct scatterlist *sg; + u64 addr, *src, *dst; + u32 rest, len; + int ret = 0; + u32 i; + + if (!vdesc->sg_len) + return 0; + + if (q->dir == DMA_MEM_TO_DEV) { + dst = &vdesc->dev_addr; + src = &addr; + } else { + dst = &addr; + src = &vdesc->dev_addr; + } + + for_each_sg(vdesc->sgl, sg, vdesc->sg_len, i) { + addr = sg_dma_address(sg) + vdesc->sg_off; + rest = sg_dma_len(sg) - vdesc->sg_off; + while (rest) { + len = min_t(u32, rest, QDMA_MM_DESC_MAX_LEN); + desc = qdma_get_desc(q); + if (!desc) { + ret = -EBUSY; + goto out; + } + + desc->src_addr = cpu_to_le64(*src); + desc->dst_addr = cpu_to_le64(*dst); + desc->len = cpu_to_le32(len); + + vdesc->dev_addr += len; + vdesc->sg_off += len; + vdesc->pending_descs++; + addr += len; + rest -= len; + } + vdesc->sg_off = 0; + } +out: + vdesc->sg_len -= i; + vdesc->pidx = q->pidx; + return ret; +} + +static void qdma_fill_pending_vdesc(struct qdma_queue *q) +{ + struct virt_dma_chan *vc = &q->vchan; + struct qdma_mm_vdesc *vdesc = NULL; + struct virt_dma_desc *vd; + int ret; + + if (!list_empty(&vc->desc_issued)) { + vd = &q->issued_vdesc->vdesc; + list_for_each_entry_from(vd, &vc->desc_issued, node) { + vdesc = to_qdma_vdesc(vd); + ret = qdma_hw_enqueue(q, vdesc); + if (ret) { + q->issued_vdesc = vdesc; + return; + } + } + q->issued_vdesc = vdesc; + } + + if (list_empty(&vc->desc_submitted)) + return; + + if (q->submitted_vdesc) + vd = &q->submitted_vdesc->vdesc; + else + vd = list_first_entry(&vc->desc_submitted, typeof(*vd), node); + + list_for_each_entry_from(vd, &vc->desc_submitted, node) { + vdesc = to_qdma_vdesc(vd); + ret = qdma_hw_enqueue(q, vdesc); + if (ret) + break; + } + q->submitted_vdesc = vdesc; +} + +static dma_cookie_t qdma_tx_submit(struct dma_async_tx_descriptor *tx) +{ + struct virt_dma_chan *vc = to_virt_chan(tx->chan); + struct qdma_queue *q = to_qdma_queue(&vc->chan); + struct virt_dma_desc *vd; + unsigned long flags; + dma_cookie_t cookie; + + vd = container_of(tx, struct virt_dma_desc, tx); + spin_lock_irqsave(&vc->lock, flags); + cookie = dma_cookie_assign(tx); + + list_move_tail(&vd->node, &vc->desc_submitted); + qdma_fill_pending_vdesc(q); + spin_unlock_irqrestore(&vc->lock, flags); + + return cookie; +} + +static struct dma_async_tx_descriptor * +qdma_prep_device_sg(struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction dir, + unsigned long flags, void *context) +{ + struct qdma_queue *q = to_qdma_queue(chan); + struct dma_async_tx_descriptor *tx; + struct qdma_mm_vdesc *vdesc; + + vdesc = kzalloc(sizeof(*vdesc), GFP_NOWAIT); + if (!vdesc) + return NULL; + vdesc->sgl = sgl; + vdesc->sg_len = sg_len; + if (dir == DMA_MEM_TO_DEV) + vdesc->dev_addr = q->cfg.dst_addr; + else + vdesc->dev_addr = q->cfg.src_addr; + + tx = vchan_tx_prep(&q->vchan, &vdesc->vdesc, flags); + tx->tx_submit = qdma_tx_submit; + + return tx; +} + +static int qdma_device_config(struct dma_chan *chan, + struct dma_slave_config *cfg) +{ + struct qdma_queue *q = to_qdma_queue(chan); + + memcpy(&q->cfg, cfg, sizeof(*cfg)); + + return 0; +} + +static int qdma_arm_err_intr(const struct qdma_device *qdev) +{ + u32 value = 0; + + qdma_set_field(qdev, &value, QDMA_REGF_ERR_INT_FUNC, qdev->fid); + qdma_set_field(qdev, &value, QDMA_REGF_ERR_INT_VEC, qdev->err_irq_idx); + qdma_set_field(qdev, &value, QDMA_REGF_ERR_INT_ARM, 1); + + return qdma_reg_write(qdev, &value, QDMA_REGO_ERR_INT); +} + +static irqreturn_t qdma_error_isr(int irq, void *data) +{ + struct qdma_device *qdev = data; + u32 err_stat = 0; + int ret; + + ret = qdma_reg_read(qdev, &err_stat, QDMA_REGO_ERR_STAT); + if (ret) { + qdma_err(qdev, "read error state failed, ret %d", ret); + goto out; + } + + qdma_err(qdev, "global error %d", err_stat); + ret = qdma_reg_write(qdev, &err_stat, QDMA_REGO_ERR_STAT); + if (ret) + qdma_err(qdev, "clear error state failed, ret %d", ret); + +out: + qdma_arm_err_intr(qdev); + return IRQ_HANDLED; +} + +static irqreturn_t qdma_queue_isr(int irq, void *data) +{ + struct qdma_intr_ring *intr = data; + struct qdma_queue *q = NULL; + struct qdma_device *qdev; + u32 index, comp_desc; + u64 intr_ent; + u8 color; + int ret; + u16 qid; + + qdev = intr->qdev; + index = intr->cidx; + while (1) { + struct virt_dma_desc *vd; + struct qdma_mm_vdesc *vdesc; + unsigned long flags; + u32 cidx; + + intr_ent = le64_to_cpu(intr->base[index]); + color = FIELD_GET(QDMA_INTR_MASK_COLOR, intr_ent); + if (color != intr->color) + break; + + qid = FIELD_GET(QDMA_INTR_MASK_QID, intr_ent); + if (FIELD_GET(QDMA_INTR_MASK_TYPE, intr_ent)) + q = qdev->c2h_queues; + else + q = qdev->h2c_queues; + q += qid; + + cidx = FIELD_GET(QDMA_INTR_MASK_CIDX, intr_ent); + + spin_lock_irqsave(&q->vchan.lock, flags); + comp_desc = (cidx - q->cidx) & q->idx_mask; + + vd = vchan_next_desc(&q->vchan); + if (!vd) + goto skip; + + vdesc = to_qdma_vdesc(vd); + while (comp_desc > vdesc->pending_descs) { + list_del(&vd->node); + vchan_cookie_complete(vd); + comp_desc -= vdesc->pending_descs; + vd = vchan_next_desc(&q->vchan); + vdesc = to_qdma_vdesc(vd); + } + vdesc->pending_descs -= comp_desc; + if (!vdesc->pending_descs && QDMA_VDESC_QUEUED(vdesc)) { + list_del(&vd->node); + vchan_cookie_complete(vd); + } + q->cidx = cidx; + + qdma_fill_pending_vdesc(q); + qdma_xfer_start(q); + +skip: + spin_unlock_irqrestore(&q->vchan.lock, flags); + + /* + * Wrap the index value and flip the expected color value if + * interrupt aggregation PIDX has wrapped around. + */ + index++; + index &= QDMA_INTR_RING_IDX_MASK; + if (!index) + intr->color = !intr->color; + } + + /* + * Update the software interrupt aggregation ring CIDX if a valid entry + * was found. + */ + if (q) { + qdma_dbg(qdev, "update intr ring%d %d", intr->ridx, index); + + /* + * Record the last read index of status descriptor from the + * interrupt aggregation ring. + */ + intr->cidx = index; + + ret = qdma_update_cidx(q, intr->ridx, index); + if (ret) { + qdma_err(qdev, "Failed to update IRQ CIDX"); + return IRQ_NONE; + } + } + + return IRQ_HANDLED; +} + +static int qdma_init_error_irq(struct qdma_device *qdev) +{ + struct device *dev = &qdev->pdev->dev; + int ret; + u32 vec; + + vec = qdev->queue_irq_start - 1; + + ret = devm_request_threaded_irq(dev, vec, NULL, qdma_error_isr, + IRQF_ONESHOT, "amd-qdma-error", qdev); + if (ret) { + qdma_err(qdev, "Failed to request error IRQ vector: %d", vec); + return ret; + } + + ret = qdma_arm_err_intr(qdev); + if (ret) + qdma_err(qdev, "Failed to arm err interrupt, ret %d", ret); + + return ret; +} + +static int qdmam_alloc_qintr_rings(struct qdma_device *qdev) +{ + u32 ctxt[QDMA_CTXT_REGMAP_LEN]; + struct device *dev = &qdev->pdev->dev; + struct qdma_intr_ring *ring; + struct qdma_ctxt_intr intr_ctxt; + u32 vector; + int ret, i; + + qdev->qintr_ring_num = qdev->queue_irq_num; + qdev->qintr_rings = devm_kcalloc(dev, qdev->qintr_ring_num, + sizeof(*qdev->qintr_rings), + GFP_KERNEL); + if (!qdev->qintr_rings) + return -ENOMEM; + + vector = qdev->queue_irq_start; + for (i = 0; i < qdev->qintr_ring_num; i++, vector++) { + ring = &qdev->qintr_rings[i]; + ring->qdev = qdev; + ring->msix_id = qdev->err_irq_idx + i + 1; + ring->ridx = i; + ring->color = 1; + ring->base = dmam_alloc_coherent(dev, QDMA_INTR_RING_SIZE, + &ring->dev_base, GFP_KERNEL); + if (!ring->base) { + qdma_err(qdev, "Failed to alloc intr ring %d", i); + return -ENOMEM; + } + intr_ctxt.agg_base = QDMA_INTR_RING_BASE(ring->dev_base); + intr_ctxt.size = (QDMA_INTR_RING_SIZE - 1) / 4096; + intr_ctxt.vec = ring->msix_id; + intr_ctxt.valid = true; + intr_ctxt.color = true; + ret = qdma_prog_context(qdev, QDMA_CTXT_INTR_COAL, + QDMA_CTXT_CLEAR, ring->ridx, NULL); + if (ret) { + qdma_err(qdev, "Failed clear intr ctx, ret %d", ret); + return ret; + } + + qdma_prep_intr_context(qdev, &intr_ctxt, ctxt); + ret = qdma_prog_context(qdev, QDMA_CTXT_INTR_COAL, + QDMA_CTXT_WRITE, ring->ridx, ctxt); + if (ret) { + qdma_err(qdev, "Failed setup intr ctx, ret %d", ret); + return ret; + } + + ret = devm_request_threaded_irq(dev, vector, NULL, + qdma_queue_isr, IRQF_ONESHOT, + "amd-qdma-queue", ring); + if (ret) { + qdma_err(qdev, "Failed to request irq %d", vector); + return ret; + } + } + + return 0; +} + +static int qdma_intr_init(struct qdma_device *qdev) +{ + int ret; + + ret = qdma_init_error_irq(qdev); + if (ret) { + qdma_err(qdev, "Failed to init error IRQs, ret %d", ret); + return ret; + } + + ret = qdmam_alloc_qintr_rings(qdev); + if (ret) { + qdma_err(qdev, "Failed to init queue IRQs, ret %d", ret); + return ret; + } + + return 0; +} + +static void amd_qdma_remove(struct platform_device *pdev) +{ + struct qdma_device *qdev = platform_get_drvdata(pdev); + + qdma_sgdma_control(qdev, 0); + dma_async_device_unregister(&qdev->dma_dev); + + mutex_destroy(&qdev->ctxt_lock); +} + +static int amd_qdma_probe(struct platform_device *pdev) +{ + struct qdma_platdata *pdata = dev_get_platdata(&pdev->dev); + struct qdma_device *qdev; + struct resource *res; + void __iomem *regs; + int ret; + + qdev = devm_kzalloc(&pdev->dev, sizeof(*qdev), GFP_KERNEL); + if (!qdev) + return -ENOMEM; + + platform_set_drvdata(pdev, qdev); + qdev->pdev = pdev; + mutex_init(&qdev->ctxt_lock); + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + qdma_err(qdev, "Failed to get IRQ resource"); + ret = -ENODEV; + goto failed; + } + qdev->err_irq_idx = pdata->irq_index; + qdev->queue_irq_start = res->start + 1; + qdev->queue_irq_num = resource_size(res) - 1; + + regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(regs)) { + ret = PTR_ERR(regs); + qdma_err(qdev, "Failed to map IO resource, err %d", ret); + goto failed; + } + + qdev->regmap = devm_regmap_init_mmio(&pdev->dev, regs, + &qdma_regmap_config); + if (IS_ERR(qdev->regmap)) { + ret = PTR_ERR(qdev->regmap); + qdma_err(qdev, "Regmap init failed, err %d", ret); + goto failed; + } + + ret = qdma_device_verify(qdev); + if (ret) + goto failed; + + ret = qdma_get_hw_info(qdev); + if (ret) + goto failed; + + INIT_LIST_HEAD(&qdev->dma_dev.channels); + + ret = qdma_device_setup(qdev); + if (ret) + goto failed; + + ret = qdma_intr_init(qdev); + if (ret) { + qdma_err(qdev, "Failed to initialize IRQs %d", ret); + goto failed_disable_engine; + } + + dma_cap_set(DMA_SLAVE, qdev->dma_dev.cap_mask); + dma_cap_set(DMA_PRIVATE, qdev->dma_dev.cap_mask); + + qdev->dma_dev.dev = &pdev->dev; + qdev->dma_dev.filter.map = pdata->device_map; + qdev->dma_dev.filter.mapcnt = qdev->chan_num * 2; + qdev->dma_dev.filter.fn = qdma_filter_fn; + qdev->dma_dev.device_alloc_chan_resources = qdma_alloc_queue_resources; + qdev->dma_dev.device_free_chan_resources = qdma_free_queue_resources; + qdev->dma_dev.device_prep_slave_sg = qdma_prep_device_sg; + qdev->dma_dev.device_config = qdma_device_config; + qdev->dma_dev.device_issue_pending = qdma_issue_pending; + qdev->dma_dev.device_tx_status = dma_cookie_status; + qdev->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + + ret = dma_async_device_register(&qdev->dma_dev); + if (ret) { + qdma_err(qdev, "Failed to register AMD QDMA: %d", ret); + goto failed_disable_engine; + } + + return 0; + +failed_disable_engine: + qdma_sgdma_control(qdev, 0); +failed: + mutex_destroy(&qdev->ctxt_lock); + qdma_err(qdev, "Failed to probe AMD QDMA driver"); + return ret; +} + +static struct platform_driver amd_qdma_driver = { + .driver = { + .name = "amd-qdma", + }, + .probe = amd_qdma_probe, + .remove_new = amd_qdma_remove, +}; + +module_platform_driver(amd_qdma_driver); + +MODULE_DESCRIPTION("AMD QDMA driver"); +MODULE_AUTHOR("XRT Team "); +MODULE_LICENSE("GPL"); diff --git a/drivers/dma/amd/qdma/qdma.h b/drivers/dma/amd/qdma/qdma.h new file mode 100644 index 000000000000..94089f1f0c11 --- /dev/null +++ b/drivers/dma/amd/qdma/qdma.h @@ -0,0 +1,266 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * DMA header for AMD Queue-based DMA Subsystem + * + * Copyright (C) 2023-2024, Advanced Micro Devices, Inc. + */ + +#ifndef __QDMA_H +#define __QDMA_H + +#include +#include +#include +#include +#include + +#include "../../virt-dma.h" + +#define DISABLE 0 +#define ENABLE 1 + +#define QDMA_MIN_IRQ 3 +#define QDMA_INTR_NAME_MAX_LEN 30 +#define QDMA_INTR_PREFIX "amd-qdma" + +#define QDMA_IDENTIFIER 0x1FD3 +#define QDMA_DEFAULT_RING_SIZE (BIT(10) + 1) +#define QDMA_DEFAULT_RING_ID 0 +#define QDMA_POLL_INTRVL_US 10 /* 10us */ +#define QDMA_POLL_TIMEOUT_US (500 * 1000) /* 500ms */ +#define QDMA_DMAP_REG_STRIDE 16 +#define QDMA_CTXT_REGMAP_LEN 8 /* 8 regs */ +#define QDMA_MM_DESC_SIZE 32 /* Bytes */ +#define QDMA_MM_DESC_LEN_BITS 28 +#define QDMA_MM_DESC_MAX_LEN (BIT(QDMA_MM_DESC_LEN_BITS) - 1) +#define QDMA_MIN_DMA_ALLOC_SIZE 4096 +#define QDMA_INTR_RING_SIZE BIT(13) +#define QDMA_INTR_RING_IDX_MASK GENMASK(9, 0) +#define QDMA_INTR_RING_BASE(_addr) ((_addr) >> 12) + +#define QDMA_IDENTIFIER_REGOFF 0x0 +#define QDMA_IDENTIFIER_MASK GENMASK(31, 16) +#define QDMA_QUEUE_ARM_BIT BIT(16) + +#define qdma_err(qdev, fmt, args...) \ + dev_err(&(qdev)->pdev->dev, fmt, ##args) + +#define qdma_dbg(qdev, fmt, args...) \ + dev_dbg(&(qdev)->pdev->dev, fmt, ##args) + +#define qdma_info(qdev, fmt, args...) \ + dev_info(&(qdev)->pdev->dev, fmt, ##args) + +enum qdma_reg_fields { + QDMA_REGF_IRQ_ENABLE, + QDMA_REGF_WBK_ENABLE, + QDMA_REGF_WBI_CHECK, + QDMA_REGF_IRQ_ARM, + QDMA_REGF_IRQ_VEC, + QDMA_REGF_IRQ_AGG, + QDMA_REGF_WBI_INTVL_ENABLE, + QDMA_REGF_MRKR_DISABLE, + QDMA_REGF_QUEUE_ENABLE, + QDMA_REGF_QUEUE_MODE, + QDMA_REGF_DESC_BASE, + QDMA_REGF_DESC_SIZE, + QDMA_REGF_RING_ID, + QDMA_REGF_CMD_INDX, + QDMA_REGF_CMD_CMD, + QDMA_REGF_CMD_TYPE, + QDMA_REGF_CMD_BUSY, + QDMA_REGF_QUEUE_COUNT, + QDMA_REGF_QUEUE_MAX, + QDMA_REGF_QUEUE_BASE, + QDMA_REGF_FUNCTION_ID, + QDMA_REGF_INTR_AGG_BASE, + QDMA_REGF_INTR_VECTOR, + QDMA_REGF_INTR_SIZE, + QDMA_REGF_INTR_VALID, + QDMA_REGF_INTR_COLOR, + QDMA_REGF_INTR_FUNCTION_ID, + QDMA_REGF_ERR_INT_FUNC, + QDMA_REGF_ERR_INT_VEC, + QDMA_REGF_ERR_INT_ARM, + QDMA_REGF_MAX +}; + +enum qdma_regs { + QDMA_REGO_CTXT_DATA, + QDMA_REGO_CTXT_CMD, + QDMA_REGO_CTXT_MASK, + QDMA_REGO_MM_H2C_CTRL, + QDMA_REGO_MM_C2H_CTRL, + QDMA_REGO_QUEUE_COUNT, + QDMA_REGO_RING_SIZE, + QDMA_REGO_H2C_PIDX, + QDMA_REGO_C2H_PIDX, + QDMA_REGO_INTR_CIDX, + QDMA_REGO_FUNC_ID, + QDMA_REGO_ERR_INT, + QDMA_REGO_ERR_STAT, + QDMA_REGO_MAX +}; + +struct qdma_reg_field { + u16 lsb; /* Least significant bit of field */ + u16 msb; /* Most significant bit of field */ +}; + +struct qdma_reg { + u32 off; + u32 count; +}; + +#define QDMA_REGF(_msb, _lsb) { \ + .lsb = (_lsb), \ + .msb = (_msb), \ +} + +#define QDMA_REGO(_off, _count) { \ + .off = (_off), \ + .count = (_count), \ +} + +enum qdma_desc_size { + QDMA_DESC_SIZE_8B, + QDMA_DESC_SIZE_16B, + QDMA_DESC_SIZE_32B, + QDMA_DESC_SIZE_64B, +}; + +enum qdma_queue_op_mode { + QDMA_QUEUE_OP_STREAM, + QDMA_QUEUE_OP_MM, +}; + +enum qdma_ctxt_type { + QDMA_CTXT_DESC_SW_C2H, + QDMA_CTXT_DESC_SW_H2C, + QDMA_CTXT_DESC_HW_C2H, + QDMA_CTXT_DESC_HW_H2C, + QDMA_CTXT_DESC_CR_C2H, + QDMA_CTXT_DESC_CR_H2C, + QDMA_CTXT_WRB, + QDMA_CTXT_PFTCH, + QDMA_CTXT_INTR_COAL, + QDMA_CTXT_RSVD, + QDMA_CTXT_HOST_PROFILE, + QDMA_CTXT_TIMER, + QDMA_CTXT_FMAP, + QDMA_CTXT_FNC_STS, +}; + +enum qdma_ctxt_cmd { + QDMA_CTXT_CLEAR, + QDMA_CTXT_WRITE, + QDMA_CTXT_READ, + QDMA_CTXT_INVALIDATE, + QDMA_CTXT_MAX +}; + +struct qdma_ctxt_sw_desc { + u64 desc_base; + u16 vec; +}; + +struct qdma_ctxt_intr { + u64 agg_base; + u16 vec; + u32 size; + bool valid; + bool color; +}; + +struct qdma_ctxt_fmap { + u16 qbase; + u16 qmax; +}; + +struct qdma_device; + +struct qdma_mm_desc { + __le64 src_addr; + __le32 len; + __le32 reserved1; + __le64 dst_addr; + __le64 reserved2; +} __packed; + +struct qdma_mm_vdesc { + struct virt_dma_desc vdesc; + struct qdma_queue *queue; + struct scatterlist *sgl; + u64 sg_off; + u32 sg_len; + u64 dev_addr; + u32 pidx; + u32 pending_descs; + struct dma_slave_config cfg; +}; + +#define QDMA_VDESC_QUEUED(vdesc) (!(vdesc)->sg_len) + +struct qdma_queue { + struct qdma_device *qdev; + struct virt_dma_chan vchan; + enum dma_transfer_direction dir; + struct dma_slave_config cfg; + struct qdma_mm_desc *desc_base; + struct qdma_mm_vdesc *submitted_vdesc; + struct qdma_mm_vdesc *issued_vdesc; + dma_addr_t dma_desc_base; + u32 pidx_reg; + u32 cidx_reg; + u32 ring_size; + u32 idx_mask; + u16 qid; + u32 pidx; + u32 cidx; +}; + +struct qdma_intr_ring { + struct qdma_device *qdev; + __le64 *base; + dma_addr_t dev_base; + char msix_name[QDMA_INTR_NAME_MAX_LEN]; + u32 msix_vector; + u16 msix_id; + u32 ring_size; + u16 ridx; + u16 cidx; + u8 color; +}; + +#define QDMA_INTR_MASK_PIDX GENMASK_ULL(15, 0) +#define QDMA_INTR_MASK_CIDX GENMASK_ULL(31, 16) +#define QDMA_INTR_MASK_DESC_COLOR GENMASK_ULL(32, 32) +#define QDMA_INTR_MASK_STATE GENMASK_ULL(34, 33) +#define QDMA_INTR_MASK_ERROR GENMASK_ULL(36, 35) +#define QDMA_INTR_MASK_TYPE GENMASK_ULL(38, 38) +#define QDMA_INTR_MASK_QID GENMASK_ULL(62, 39) +#define QDMA_INTR_MASK_COLOR GENMASK_ULL(63, 63) + +struct qdma_device { + struct platform_device *pdev; + struct dma_device dma_dev; + struct regmap *regmap; + struct mutex ctxt_lock; /* protect ctxt registers */ + const struct qdma_reg_field *rfields; + const struct qdma_reg *roffs; + struct qdma_queue *h2c_queues; + struct qdma_queue *c2h_queues; + struct qdma_intr_ring *qintr_rings; + u32 qintr_ring_num; + u32 qintr_ring_idx; + u32 chan_num; + u32 queue_irq_start; + u32 queue_irq_num; + u32 err_irq_idx; + u32 fid; +}; + +extern const struct qdma_reg qdma_regos_default[QDMA_REGO_MAX]; +extern const struct qdma_reg_field qdma_regfs_default[QDMA_REGF_MAX]; + +#endif /* __QDMA_H */ diff --git a/include/linux/platform_data/amd_qdma.h b/include/linux/platform_data/amd_qdma.h new file mode 100644 index 000000000000..576d952f97ed --- /dev/null +++ b/include/linux/platform_data/amd_qdma.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices, Inc. + */ + +#ifndef _PLATDATA_AMD_QDMA_H +#define _PLATDATA_AMD_QDMA_H + +#include + +/** + * struct qdma_queue_info - DMA queue information. This information is used to + * match queue when DMA channel is requested + * @dir: Channel transfer direction + */ +struct qdma_queue_info { + enum dma_transfer_direction dir; +}; + +#define QDMA_FILTER_PARAM(qinfo) ((void *)(qinfo)) + +struct dma_slave_map; + +/** + * struct qdma_platdata - Platform specific data for QDMA engine + * @max_mm_channels: Maximum number of MM DMA channels in each direction + * @device_map: DMA slave map + * @irq_index: The index of first IRQ + */ +struct qdma_platdata { + u32 max_mm_channels; + u32 irq_index; + struct dma_slave_map *device_map; +}; + +#endif /* _PLATDATA_AMD_QDMA_H */ -- cgit v1.2.3 From c4a315eaf8eff0d3234600e13db7e7c71c0b3405 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 21 Aug 2024 14:14:56 +0200 Subject: gpio: ath79: remove support for platform data There are no more board files defining platform data for this driver so remove the header and support from the driver. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20240821121456.19553-4-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-ath79.c | 22 ++++++---------------- include/linux/platform_data/gpio-ath79.h | 16 ---------------- 2 files changed, 6 insertions(+), 32 deletions(-) delete mode 100644 include/linux/platform_data/gpio-ath79.h (limited to 'include/linux/platform_data') diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 211faffbef32..de4cc12e5e03 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #define AR71XX_GPIO_REG_OE 0x00 @@ -225,9 +224,7 @@ MODULE_DEVICE_TABLE(of, ath79_gpio_of_match); static int ath79_gpio_probe(struct platform_device *pdev) { - struct ath79_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; struct ath79_gpio_ctrl *ctrl; struct gpio_irq_chip *girq; u32 ath79_gpio_count; @@ -238,21 +235,14 @@ static int ath79_gpio_probe(struct platform_device *pdev) if (!ctrl) return -ENOMEM; - if (np) { - err = device_property_read_u32(dev, "ngpios", &ath79_gpio_count); - if (err) { - dev_err(dev, "ngpios property is not valid\n"); - return err; - } - oe_inverted = device_is_compatible(dev, "qca,ar9340-gpio"); - } else if (pdata) { - ath79_gpio_count = pdata->ngpios; - oe_inverted = pdata->oe_inverted; - } else { - dev_err(dev, "No DT node or platform data found\n"); - return -EINVAL; + err = device_property_read_u32(dev, "ngpios", &ath79_gpio_count); + if (err) { + dev_err(dev, "ngpios property is not valid\n"); + return err; } + oe_inverted = device_is_compatible(dev, "qca,ar9340-gpio"); + if (ath79_gpio_count >= 32) { dev_err(dev, "ngpios must be less than 32\n"); return -EINVAL; diff --git a/include/linux/platform_data/gpio-ath79.h b/include/linux/platform_data/gpio-ath79.h deleted file mode 100644 index 3ea6dd942c27..000000000000 --- a/include/linux/platform_data/gpio-ath79.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Atheros AR7XXX/AR9XXX GPIO controller platform data - * - * Copyright (C) 2015 Alban Bedel - */ - -#ifndef __LINUX_PLATFORM_DATA_GPIO_ATH79_H -#define __LINUX_PLATFORM_DATA_GPIO_ATH79_H - -struct ath79_gpio_platform_data { - unsigned ngpios; - bool oe_inverted; -}; - -#endif -- cgit v1.2.3 From 631598c419985327110135efb696d9f9fe67bffd Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 14 Aug 2024 11:26:29 +0200 Subject: iio: dac: ad5449: drop support for platform data There are no longer any users of the platform data struct. Remove support for it from the driver. Signed-off-by: Bartosz Golaszewski Link: https://patch.msgid.link/20240814092629.9862-1-brgl@bgdev.pl Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5449.c | 15 ++------------ include/linux/platform_data/ad5449.h | 39 ------------------------------------ 2 files changed, 2 insertions(+), 52 deletions(-) delete mode 100644 include/linux/platform_data/ad5449.h (limited to 'include/linux/platform_data') diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c index 4572d6f49275..953fcfa2110b 100644 --- a/drivers/iio/dac/ad5449.c +++ b/drivers/iio/dac/ad5449.c @@ -20,8 +20,6 @@ #include #include -#include - #define AD5449_MAX_CHANNELS 2 #define AD5449_MAX_VREFS 2 @@ -268,7 +266,6 @@ static const char *ad5449_vref_name(struct ad5449 *st, int n) static int ad5449_spi_probe(struct spi_device *spi) { - struct ad5449_platform_data *pdata = spi->dev.platform_data; const struct spi_device_id *id = spi_get_device_id(spi); struct iio_dev *indio_dev; struct ad5449 *st; @@ -306,16 +303,8 @@ static int ad5449_spi_probe(struct spi_device *spi) mutex_init(&st->lock); if (st->chip_info->has_ctrl) { - unsigned int ctrl = 0x00; - if (pdata) { - if (pdata->hardware_clear_to_midscale) - ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE; - ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET; - st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED; - } else { - st->has_sdo = true; - } - ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl); + st->has_sdo = true; + ad5449_write(indio_dev, AD5449_CMD_CTRL, 0x0); } ret = iio_device_register(indio_dev); diff --git a/include/linux/platform_data/ad5449.h b/include/linux/platform_data/ad5449.h deleted file mode 100644 index d687ef5726c2..000000000000 --- a/include/linux/platform_data/ad5449.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog - * Converter driver. - * - * Copyright 2012 Analog Devices Inc. - * Author: Lars-Peter Clausen - */ - -#ifndef __LINUX_PLATFORM_DATA_AD5449_H__ -#define __LINUX_PLATFORM_DATA_AD5449_H__ - -/** - * enum ad5449_sdo_mode - AD5449 SDO pin configuration - * @AD5449_SDO_DRIVE_FULL: Drive the SDO pin with full strength. - * @AD5449_SDO_DRIVE_WEAK: Drive the SDO pin with not full strength. - * @AD5449_SDO_OPEN_DRAIN: Operate the SDO pin in open-drain mode. - * @AD5449_SDO_DISABLED: Disable the SDO pin, in this mode it is not possible to - * read back from the device. - */ -enum ad5449_sdo_mode { - AD5449_SDO_DRIVE_FULL = 0x0, - AD5449_SDO_DRIVE_WEAK = 0x1, - AD5449_SDO_OPEN_DRAIN = 0x2, - AD5449_SDO_DISABLED = 0x3, -}; - -/** - * struct ad5449_platform_data - Platform data for the ad5449 DAC driver - * @sdo_mode: SDO pin mode - * @hardware_clear_to_midscale: Whether asserting the hardware CLR pin sets the - * outputs to midscale (true) or to zero scale(false). - */ -struct ad5449_platform_data { - enum ad5449_sdo_mode sdo_mode; - bool hardware_clear_to_midscale; -}; - -#endif -- cgit v1.2.3 From d29e741cad3f8f41df1834bf74df79380c1c6c6d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 19 Aug 2024 17:17:04 +0200 Subject: gpio: davinci: drop platform data support There are no more any board files that use the platform data for gpio-davinci. We can remove the header defining it and port the code to no longer store any context in pdata. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20240819151705.37258-1-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-davinci.c | 89 +++++++++--------------------- include/linux/platform_data/gpio-davinci.h | 21 ------- 2 files changed, 25 insertions(+), 85 deletions(-) delete mode 100644 include/linux/platform_data/gpio-davinci.h (limited to 'include/linux/platform_data') diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 1d0175d6350b..7763b99f814a 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -154,74 +153,37 @@ davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) value ? &g->set_data : &g->clr_data); } -static struct davinci_gpio_platform_data * -davinci_gpio_get_pdata(struct platform_device *pdev) -{ - struct device_node *dn = pdev->dev.of_node; - struct davinci_gpio_platform_data *pdata; - int ret; - u32 val; - - if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) - return dev_get_platdata(&pdev->dev); - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - ret = of_property_read_u32(dn, "ti,ngpio", &val); - if (ret) - goto of_err; - - pdata->ngpio = val; - - ret = of_property_read_u32(dn, "ti,davinci-gpio-unbanked", &val); - if (ret) - goto of_err; - - pdata->gpio_unbanked = val; - - return pdata; - -of_err: - dev_err(&pdev->dev, "Populating pdata from DT failed: err %d\n", ret); - return NULL; -} - static int davinci_gpio_probe(struct platform_device *pdev) { int bank, i, ret = 0; - unsigned int ngpio, nbank, nirq; + unsigned int ngpio, nbank, nirq, gpio_unbanked; struct davinci_gpio_controller *chips; - struct davinci_gpio_platform_data *pdata; struct device *dev = &pdev->dev; - - pdata = davinci_gpio_get_pdata(pdev); - if (!pdata) { - dev_err(dev, "No platform data found\n"); - return -EINVAL; - } - - dev->platform_data = pdata; + struct device_node *dn = dev_of_node(dev); /* * The gpio banks conceptually expose a segmented bitmap, * and "ngpio" is one more than the largest zero-based * bit index that's valid. */ - ngpio = pdata->ngpio; - if (ngpio == 0) { - dev_err(dev, "How many GPIOs?\n"); - return -EINVAL; - } + ret = of_property_read_u32(dn, "ti,ngpio", &ngpio); + if (ret) + return dev_err_probe(dev, ret, "Failed to get the number of GPIOs\n"); + if (ngpio == 0) + return dev_err_probe(dev, -EINVAL, "How many GPIOs?\n"); /* * If there are unbanked interrupts then the number of * interrupts is equal to number of gpios else all are banked so * number of interrupts is equal to number of banks(each with 16 gpios) */ - if (pdata->gpio_unbanked) - nirq = pdata->gpio_unbanked; + ret = of_property_read_u32(dn, "ti,davinci-gpio-unbanked", + &gpio_unbanked); + if (ret) + return dev_err_probe(dev, ret, "Failed to get the unbanked GPIOs property\n"); + + if (gpio_unbanked) + nirq = gpio_unbanked; else nirq = DIV_ROUND_UP(ngpio, 16); @@ -252,7 +214,7 @@ static int davinci_gpio_probe(struct platform_device *pdev) chips->chip.set = davinci_gpio_set; chips->chip.ngpio = ngpio; - chips->chip.base = pdata->no_auto_base ? pdata->base : -1; + chips->chip.base = -1; #ifdef CONFIG_OF_GPIO chips->chip.parent = dev; @@ -261,6 +223,8 @@ static int davinci_gpio_probe(struct platform_device *pdev) #endif spin_lock_init(&chips->lock); + chips->gpio_unbanked = gpio_unbanked; + nbank = DIV_ROUND_UP(ngpio, 32); for (bank = 0; bank < nbank; bank++) chips->regs[bank] = gpio_base + offset_array[bank]; @@ -488,7 +452,6 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) unsigned ngpio; struct device *dev = &pdev->dev; struct davinci_gpio_controller *chips = platform_get_drvdata(pdev); - struct davinci_gpio_platform_data *pdata = dev->platform_data; struct davinci_gpio_regs __iomem *g; struct irq_domain *irq_domain = NULL; struct irq_chip *irq_chip; @@ -502,7 +465,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) if (dev->of_node) gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)device_get_match_data(dev); - ngpio = pdata->ngpio; + ngpio = chips->chip.ngpio; clk = devm_clk_get(dev, "gpio"); if (IS_ERR(clk)) { @@ -514,7 +477,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) if (ret) return ret; - if (!pdata->gpio_unbanked) { + if (chips->gpio_unbanked) { irq = devm_irq_alloc_descs(dev, -1, 0, ngpio, 0); if (irq < 0) { dev_err(dev, "Couldn't allocate IRQ numbers\n"); @@ -546,11 +509,11 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) * controller only handling trigger modes. We currently assume no * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs. */ - if (pdata->gpio_unbanked) { + if (chips->gpio_unbanked) { /* pass "bank 0" GPIO IRQs to AINTC */ chips->chip.to_irq = gpio_to_irq_unbanked; - chips->gpio_unbanked = pdata->gpio_unbanked; - binten = GENMASK(pdata->gpio_unbanked / 16, 0); + + binten = GENMASK(chips->gpio_unbanked / 16, 0); /* AINTC handles mask/unmask; GPIO handles triggering */ irq = chips->irqs[0]; @@ -564,7 +527,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) writel_relaxed(~0, &g->set_rising); /* set the direct IRQs up to use that irqchip */ - for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++) { + for (gpio = 0; gpio < chips->gpio_unbanked; gpio++) { irq_set_chip(chips->irqs[gpio], irq_chip); irq_set_handler_data(chips->irqs[gpio], chips); irq_set_status_flags(chips->irqs[gpio], @@ -675,8 +638,7 @@ static void davinci_gpio_restore_context(struct davinci_gpio_controller *chips, static int davinci_gpio_suspend(struct device *dev) { struct davinci_gpio_controller *chips = dev_get_drvdata(dev); - struct davinci_gpio_platform_data *pdata = dev_get_platdata(dev); - u32 nbank = DIV_ROUND_UP(pdata->ngpio, 32); + u32 nbank = DIV_ROUND_UP(chips->chip.ngpio, 32); davinci_gpio_save_context(chips, nbank); @@ -686,8 +648,7 @@ static int davinci_gpio_suspend(struct device *dev) static int davinci_gpio_resume(struct device *dev) { struct davinci_gpio_controller *chips = dev_get_drvdata(dev); - struct davinci_gpio_platform_data *pdata = dev_get_platdata(dev); - u32 nbank = DIV_ROUND_UP(pdata->ngpio, 32); + u32 nbank = DIV_ROUND_UP(chips->chip.ngpio, 32); davinci_gpio_restore_context(chips, nbank); diff --git a/include/linux/platform_data/gpio-davinci.h b/include/linux/platform_data/gpio-davinci.h deleted file mode 100644 index b82e44662efe..000000000000 --- a/include/linux/platform_data/gpio-davinci.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * DaVinci GPIO Platform Related Defines - * - * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/ - */ - -#ifndef __DAVINCI_GPIO_PLATFORM_H -#define __DAVINCI_GPIO_PLATFORM_H - -struct davinci_gpio_platform_data { - bool no_auto_base; - u32 base; - u32 ngpio; - u32 gpio_unbanked; -}; - -/* Convert GPIO signal to GPIO pin number */ -#define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio)) - -#endif -- cgit v1.2.3 From f820b43754cdbd078a0d17122b281f42cbcd2155 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 23 Aug 2024 22:50:27 -0700 Subject: Input: zforce_ts - remove support for platfrom data There are no in-tree users of platform data and any new ones should either use device tree or static device properties, so let's remove platform data support. Tested-by: Andreas Kemnade # Tolino Shine2HD Link: https://lore.kernel.org/r/20240824055047.1706392-4-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/zforce_ts.c | 56 ++++++++++----------------------- include/linux/platform_data/zforce_ts.h | 15 --------- 2 files changed, 16 insertions(+), 55 deletions(-) delete mode 100644 include/linux/platform_data/zforce_ts.h (limited to 'include/linux/platform_data') diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index 350cec8508a3..5a8f79b800e6 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -9,21 +9,19 @@ * Author: Pieter Truter */ -#include -#include -#include -#include -#include -#include #include -#include #include -#include +#include +#include +#include #include #include -#include -#include +#include +#include #include +#include +#include +#include #define WAIT_TIMEOUT msecs_to_jiffies(1000) @@ -108,7 +106,6 @@ struct zforce_ts { struct i2c_client *client; struct input_dev *input; struct touchscreen_properties prop; - const struct zforce_ts_platdata *pdata; char phys[32]; struct regulator *reg_vdd; @@ -702,39 +699,24 @@ static void zforce_reset(void *data) regulator_disable(ts->reg_vdd); } -static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev) +static void zforce_ts_parse_legacy_properties(struct zforce_ts *ts) { - struct zforce_ts_platdata *pdata; - struct device_node *np = dev->of_node; - - if (!np) - return ERR_PTR(-ENOENT); + u32 x_max = 0; + u32 y_max = 0; - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - dev_err(dev, "failed to allocate platform data\n"); - return ERR_PTR(-ENOMEM); - } - - of_property_read_u32(np, "x-size", &pdata->x_max); - of_property_read_u32(np, "y-size", &pdata->y_max); + device_property_read_u32(&ts->client->dev, "x-size", &x_max); + input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, x_max, 0, 0); - return pdata; + device_property_read_u32(&ts->client->dev, "y-size", &y_max); + input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, y_max, 0, 0); } static int zforce_probe(struct i2c_client *client) { - const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); struct zforce_ts *ts; struct input_dev *input_dev; int ret; - if (!pdata) { - pdata = zforce_parse_dt(&client->dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - } - ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL); if (!ts) return -ENOMEM; @@ -822,7 +804,6 @@ static int zforce_probe(struct i2c_client *client) mutex_init(&ts->access_mutex); mutex_init(&ts->command_mutex); - ts->pdata = pdata; ts->client = client; ts->input = input_dev; @@ -837,12 +818,7 @@ static int zforce_probe(struct i2c_client *client) __set_bit(EV_SYN, input_dev->evbit); __set_bit(EV_ABS, input_dev->evbit); - /* For multi touch */ - input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, - pdata->x_max, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, - pdata->y_max, 0, 0); - + zforce_ts_parse_legacy_properties(ts); touchscreen_parse_properties(input_dev, true, &ts->prop); if (ts->prop.max_x == 0 || ts->prop.max_y == 0) { dev_err(&client->dev, "no size specified\n"); diff --git a/include/linux/platform_data/zforce_ts.h b/include/linux/platform_data/zforce_ts.h deleted file mode 100644 index 2463a4a856a6..000000000000 --- a/include/linux/platform_data/zforce_ts.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* drivers/input/touchscreen/zforce.c - * - * Copyright (C) 2012-2013 MundoReader S.L. - */ - -#ifndef _LINUX_INPUT_ZFORCE_TS_H -#define _LINUX_INPUT_ZFORCE_TS_H - -struct zforce_ts_platdata { - unsigned int x_max; - unsigned int y_max; -}; - -#endif /* _LINUX_INPUT_ZFORCE_TS_H */ -- cgit v1.2.3 From 23de126f9248a2f9218175ea0dd1c1403e334440 Mon Sep 17 00:00:00 2001 From: Pieter Van Trappen Date: Wed, 4 Sep 2024 08:27:42 +0200 Subject: net: dsa: microchip: replace unclear KSZ8830 strings Replace ksz8830 with ksz88x3 for CHIP_ID definition and other strings. This due to KSZ8830 not being an actual switch but the Chip ID shared among KSZ8863/8873 switches, impossible to differentiate from their Chip ID or Revision ID registers. Now all KSZ*_CHIP_ID macros refer to actual, existing switches which removes confusion. Signed-off-by: Pieter Van Trappen Acked-by: Arun Ramadoss Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz8.c | 2 +- drivers/net/dsa/microchip/ksz8863_smi.c | 4 +-- drivers/net/dsa/microchip/ksz_common.c | 48 ++++++++++++++--------------- drivers/net/dsa/microchip/ksz_common.h | 4 +-- drivers/net/dsa/microchip/ksz_spi.c | 6 ++-- include/linux/platform_data/microchip-ksz.h | 2 +- 6 files changed, 33 insertions(+), 33 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c index 7af3c0853505..da7110d67558 100644 --- a/drivers/net/dsa/microchip/ksz8.c +++ b/drivers/net/dsa/microchip/ksz8.c @@ -194,7 +194,7 @@ int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu) case KSZ8794_CHIP_ID: case KSZ8765_CHIP_ID: return ksz8795_change_mtu(dev, frame_size); - case KSZ8830_CHIP_ID: + case KSZ88X3_CHIP_ID: case KSZ8864_CHIP_ID: case KSZ8895_CHIP_ID: return ksz8863_change_mtu(dev, frame_size); diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c index 5711a59e2ac9..a8bfcd917bf7 100644 --- a/drivers/net/dsa/microchip/ksz8863_smi.c +++ b/drivers/net/dsa/microchip/ksz8863_smi.c @@ -199,11 +199,11 @@ static void ksz8863_smi_shutdown(struct mdio_device *mdiodev) static const struct of_device_id ksz8863_dt_ids[] = { { .compatible = "microchip,ksz8863", - .data = &ksz_switch_chips[KSZ8830] + .data = &ksz_switch_chips[KSZ88X3] }, { .compatible = "microchip,ksz8873", - .data = &ksz_switch_chips[KSZ8830] + .data = &ksz_switch_chips[KSZ88X3] }, { }, }; diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index cd116de3ddb8..4e8710c7cb7b 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -246,16 +246,16 @@ static const struct ksz_drive_strength ksz9477_drive_strengths[] = { { SW_DRIVE_STRENGTH_28MA, 28000 }, }; -/* ksz8830_drive_strengths - Drive strength mapping for KSZ8830, KSZ8873, .. +/* ksz88x3_drive_strengths - Drive strength mapping for KSZ8863, KSZ8873, .. * variants. * This values are documented in KSZ8873 and KSZ8863 datasheets. */ -static const struct ksz_drive_strength ksz8830_drive_strengths[] = { +static const struct ksz_drive_strength ksz88x3_drive_strengths[] = { { 0, 8000 }, { KSZ8873_DRIVE_STRENGTH_16MA, 16000 }, }; -static void ksz8830_phylink_mac_config(struct phylink_config *config, +static void ksz88x3_phylink_mac_config(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state); static void ksz_phylink_mac_config(struct phylink_config *config, @@ -265,8 +265,8 @@ static void ksz_phylink_mac_link_down(struct phylink_config *config, unsigned int mode, phy_interface_t interface); -static const struct phylink_mac_ops ksz8830_phylink_mac_ops = { - .mac_config = ksz8830_phylink_mac_config, +static const struct phylink_mac_ops ksz88x3_phylink_mac_ops = { + .mac_config = ksz88x3_phylink_mac_config, .mac_link_down = ksz_phylink_mac_link_down, .mac_link_up = ksz8_phylink_mac_link_up, }; @@ -1442,8 +1442,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { .internal_phy = {true, true, true, true, false}, }, - [KSZ8830] = { - .chip_id = KSZ8830_CHIP_ID, + [KSZ88X3] = { + .chip_id = KSZ88X3_CHIP_ID, .dev_name = "KSZ8863/KSZ8873", .num_vlans = 16, .num_alus = 0, @@ -1453,7 +1453,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 4, .ops = &ksz88xx_dev_ops, - .phylink_mac_ops = &ksz8830_phylink_mac_ops, + .phylink_mac_ops = &ksz88x3_phylink_mac_ops, .mib_names = ksz88xx_mib_names, .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -1487,7 +1487,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 4, .ops = &ksz88xx_dev_ops, - .phylink_mac_ops = &ksz8830_phylink_mac_ops, + .phylink_mac_ops = &ksz88x3_phylink_mac_ops, .mib_names = ksz88xx_mib_names, .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -1510,7 +1510,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 4, .ops = &ksz88xx_dev_ops, - .phylink_mac_ops = &ksz8830_phylink_mac_ops, + .phylink_mac_ops = &ksz88x3_phylink_mac_ops, .mib_names = ksz88xx_mib_names, .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -2724,7 +2724,7 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) struct ksz_device *dev = ds->priv; switch (dev->chip_id) { - case KSZ8830_CHIP_ID: + case KSZ88X3_CHIP_ID: /* Silicon Errata Sheet (DS80000830A): * Port 1 does not work with LinkMD Cable-Testing. * Port 1 does not respond to received PAUSE control frames. @@ -3050,7 +3050,7 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds, if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev)) proto = DSA_TAG_PROTO_KSZ8795; - if (dev->chip_id == KSZ8830_CHIP_ID || + if (dev->chip_id == KSZ88X3_CHIP_ID || dev->chip_id == KSZ8563_CHIP_ID || dev->chip_id == KSZ9893_CHIP_ID || dev->chip_id == KSZ9563_CHIP_ID) @@ -3162,7 +3162,7 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port) case KSZ8794_CHIP_ID: case KSZ8765_CHIP_ID: return KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; - case KSZ8830_CHIP_ID: + case KSZ88X3_CHIP_ID: case KSZ8864_CHIP_ID: case KSZ8895_CHIP_ID: return KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; @@ -3334,7 +3334,7 @@ phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit) return interface; } -static void ksz8830_phylink_mac_config(struct phylink_config *config, +static void ksz88x3_phylink_mac_config(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state) { @@ -3518,7 +3518,7 @@ static int ksz_switch_detect(struct ksz_device *dev) break; case KSZ88_FAMILY_ID: if (id2 == KSZ88_CHIP_ID_63) - dev->chip_id = KSZ8830_CHIP_ID; + dev->chip_id = KSZ88X3_CHIP_ID; else return -ENODEV; break; @@ -4592,24 +4592,24 @@ static int ksz9477_drive_strength_write(struct ksz_device *dev, } /** - * ksz8830_drive_strength_write() - Set the drive strength configuration for - * KSZ8830 compatible chip variants. + * ksz88x3_drive_strength_write() - Set the drive strength configuration for + * KSZ8863 compatible chip variants. * @dev: ksz device * @props: Array of drive strength properties to be set * @num_props: Number of properties in the array * - * This function applies the specified drive strength settings to KSZ8830 chip + * This function applies the specified drive strength settings to KSZ88X3 chip * variants (KSZ8873, KSZ8863). * It ensures the configurations align with what the chip variant supports and * warns or errors out on unsupported settings. * * Return: 0 on success, error code otherwise */ -static int ksz8830_drive_strength_write(struct ksz_device *dev, +static int ksz88x3_drive_strength_write(struct ksz_device *dev, struct ksz_driver_strength_prop *props, int num_props) { - size_t array_size = ARRAY_SIZE(ksz8830_drive_strengths); + size_t array_size = ARRAY_SIZE(ksz88x3_drive_strengths); int microamp; int i, ret; @@ -4622,10 +4622,10 @@ static int ksz8830_drive_strength_write(struct ksz_device *dev, } microamp = props[KSZ_DRIVER_STRENGTH_IO].value; - ret = ksz_drive_strength_to_reg(ksz8830_drive_strengths, array_size, + ret = ksz_drive_strength_to_reg(ksz88x3_drive_strengths, array_size, microamp); if (ret < 0) { - ksz_drive_strength_error(dev, ksz8830_drive_strengths, + ksz_drive_strength_error(dev, ksz88x3_drive_strengths, array_size, microamp); return ret; } @@ -4685,8 +4685,8 @@ static int ksz_parse_drive_strength(struct ksz_device *dev) return 0; switch (dev->chip_id) { - case KSZ8830_CHIP_ID: - return ksz8830_drive_strength_write(dev, of_props, + case KSZ88X3_CHIP_ID: + return ksz88x3_drive_strength_write(dev, of_props, ARRAY_SIZE(of_props)); case KSZ8795_CHIP_ID: case KSZ8794_CHIP_ID: diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index e08d5a1339f4..bec846e20682 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -200,7 +200,7 @@ enum ksz_model { KSZ8795, KSZ8794, KSZ8765, - KSZ8830, + KSZ88X3, KSZ8864, KSZ8895, KSZ9477, @@ -628,7 +628,7 @@ static inline bool ksz_is_ksz87xx(struct ksz_device *dev) static inline bool ksz_is_ksz88x3(struct ksz_device *dev) { - return dev->chip_id == KSZ8830_CHIP_ID; + return dev->chip_id == KSZ88X3_CHIP_ID; } static inline bool ksz_is_8895_family(struct ksz_device *dev) diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c index f4287310e89f..e3e341431f09 100644 --- a/drivers/net/dsa/microchip/ksz_spi.c +++ b/drivers/net/dsa/microchip/ksz_spi.c @@ -54,7 +54,7 @@ static int ksz_spi_probe(struct spi_device *spi) if (!chip) return -EINVAL; - if (chip->chip_id == KSZ8830_CHIP_ID) + if (chip->chip_id == KSZ88X3_CHIP_ID) regmap_config = ksz8863_regmap_config; else if (chip->chip_id == KSZ8795_CHIP_ID || chip->chip_id == KSZ8794_CHIP_ID || @@ -137,7 +137,7 @@ static const struct of_device_id ksz_dt_ids[] = { }, { .compatible = "microchip,ksz8863", - .data = &ksz_switch_chips[KSZ8830] + .data = &ksz_switch_chips[KSZ88X3] }, { .compatible = "microchip,ksz8864", @@ -145,7 +145,7 @@ static const struct of_device_id ksz_dt_ids[] = { }, { .compatible = "microchip,ksz8873", - .data = &ksz_switch_chips[KSZ8830] + .data = &ksz_switch_chips[KSZ88X3] }, { .compatible = "microchip,ksz8895", diff --git a/include/linux/platform_data/microchip-ksz.h b/include/linux/platform_data/microchip-ksz.h index d074019474f5..2ee1a679e592 100644 --- a/include/linux/platform_data/microchip-ksz.h +++ b/include/linux/platform_data/microchip-ksz.h @@ -27,7 +27,7 @@ enum ksz_chip_id { KSZ8795_CHIP_ID = 0x8795, KSZ8794_CHIP_ID = 0x8794, KSZ8765_CHIP_ID = 0x8765, - KSZ8830_CHIP_ID = 0x8830, + KSZ88X3_CHIP_ID = 0x8830, KSZ8864_CHIP_ID = 0x8864, KSZ8895_CHIP_ID = 0x8895, KSZ9477_CHIP_ID = 0x00947700, -- cgit v1.2.3 From d6de45e3c6f3713d3825d3e2860c11d24e0f941f Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Tue, 10 Sep 2024 00:35:03 +0200 Subject: platform/x86: asus-wmi: Disable OOBE experience on Zenbook S 16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The OOBE experience fades the keyboard backlight in & out continuously, and make the backlight uncontrollable using its device. Workaround taken from https://wiki.archlinux.org/index.php?title=ASUS_Zenbook_UM5606&diff=next&oldid=815547 Signed-off-by: Bas Nieuwenhuizen Reviewed-by: Luke D. Jones Link: https://lore.kernel.org/r/20240909223503.1445779-1-bas@basnieuwenhuizen.nl Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/asus-wmi.c | 10 ++++++++++ include/linux/platform_data/x86/asus-wmi.h | 1 + 2 files changed, 11 insertions(+) (limited to 'include/linux/platform_data') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 37636e5a38e3..321a658e4554 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1793,6 +1793,16 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_OOBE)) { + /* + * Disable OOBE state, so that e.g. the keyboard backlight + * works. + */ + rv = asus_wmi_set_devstate(ASUS_WMI_DEVID_OOBE, 1, NULL); + if (rv) + goto error; + } + error: if (rv) asus_wmi_led_exit(asus); diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 0aeeae1c1943..ae9bf7479e7b 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -62,6 +62,7 @@ #define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 #define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */ #define ASUS_WMI_DEVID_LIGHTBAR 0x00050025 +#define ASUS_WMI_DEVID_OOBE 0x0005002F /* This can only be used to disable the screen, not re-enable */ #define ASUS_WMI_DEVID_SCREENPAD_POWER 0x00050031 /* Writing a brightness re-enables the screen if disabled */ -- cgit v1.2.3 From c912ac66b3fc92acb0079fff7d030e9be0756c36 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 9 Sep 2024 15:41:05 +0300 Subject: platform/x86: intel_scu_ipc: Move intel_scu_ipc.h out of arch/x86/include/asm This is a platform/x86 library that is mostly being used by other drivers not directly under arch/x86 anyway (with the exception of the Intel MID setup code) so it makes sense that it lives under the platform_data/x86/ directory instead. No functional changes intended. Suggested-by: Andy Shevchenko Signed-off-by: Mika Westerberg Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240909124952.1152017-3-andriy.shevchenko@linux.intel.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- MAINTAINERS | 4 +- arch/x86/include/asm/intel_scu_ipc.h | 68 ------------------------- arch/x86/include/asm/intel_telemetry.h | 2 +- arch/x86/platform/intel-mid/intel-mid.c | 3 +- drivers/mfd/intel_pmc_bxt.c | 3 +- drivers/mfd/intel_soc_pmic_bxtwc.c | 3 +- drivers/mfd/intel_soc_pmic_mrfld.c | 3 +- drivers/platform/x86/intel_scu_ipc.c | 2 +- drivers/platform/x86/intel_scu_ipcutil.c | 2 +- drivers/platform/x86/intel_scu_pcidrv.c | 2 +- drivers/platform/x86/intel_scu_pltdrv.c | 2 +- drivers/usb/typec/mux/intel_pmc_mux.c | 3 +- drivers/watchdog/intel-mid_wdt.c | 3 +- include/linux/platform_data/x86/intel_scu_ipc.h | 68 +++++++++++++++++++++++++ 14 files changed, 82 insertions(+), 86 deletions(-) delete mode 100644 arch/x86/include/asm/intel_scu_ipc.h create mode 100644 include/linux/platform_data/x86/intel_scu_ipc.h (limited to 'include/linux/platform_data') diff --git a/MAINTAINERS b/MAINTAINERS index 2ba2877c095d..3f3a8d8abf87 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11471,7 +11471,6 @@ M: Andy Shevchenko L: linux-kernel@vger.kernel.org S: Supported F: arch/x86/include/asm/intel-mid.h -F: arch/x86/include/asm/intel_scu_ipc.h F: arch/x86/pci/intel_mid_pci.c F: arch/x86/platform/intel-mid/ F: drivers/extcon/extcon-intel-mrfld.c @@ -11483,6 +11482,7 @@ F: drivers/staging/media/atomisp/ F: drivers/watchdog/intel-mid_wdt.c F: include/linux/mfd/intel_soc_pmic_mrfld.h F: include/linux/platform_data/intel-mid_wdt.h +F: include/linux/platform_data/x86/intel_scu_ipc.h INTEL P-Unit IPC DRIVER M: Zha Qipeng @@ -11546,8 +11546,8 @@ F: drivers/counter/intel-qep.c INTEL SCU DRIVERS M: Mika Westerberg S: Maintained -F: arch/x86/include/asm/intel_scu_ipc.h F: drivers/platform/x86/intel_scu_* +F: include/linux/platform_data/x86/intel_scu_ipc.h INTEL SDSI DRIVER M: David E. Box diff --git a/arch/x86/include/asm/intel_scu_ipc.h b/arch/x86/include/asm/intel_scu_ipc.h deleted file mode 100644 index 8537f597d20a..000000000000 --- a/arch/x86/include/asm/intel_scu_ipc.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_X86_INTEL_SCU_IPC_H_ -#define _ASM_X86_INTEL_SCU_IPC_H_ - -#include - -struct device; -struct intel_scu_ipc_dev; - -/** - * struct intel_scu_ipc_data - Data used to configure SCU IPC - * @mem: Base address of SCU IPC MMIO registers - * @irq: The IRQ number used for SCU (optional) - */ -struct intel_scu_ipc_data { - struct resource mem; - int irq; -}; - -struct intel_scu_ipc_dev * -__intel_scu_ipc_register(struct device *parent, - const struct intel_scu_ipc_data *scu_data, - struct module *owner); - -#define intel_scu_ipc_register(parent, scu_data) \ - __intel_scu_ipc_register(parent, scu_data, THIS_MODULE) - -void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu); - -struct intel_scu_ipc_dev * -__devm_intel_scu_ipc_register(struct device *parent, - const struct intel_scu_ipc_data *scu_data, - struct module *owner); - -#define devm_intel_scu_ipc_register(parent, scu_data) \ - __devm_intel_scu_ipc_register(parent, scu_data, THIS_MODULE) - -struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void); -void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu); -struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev); - -int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, - u8 *data); -int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, - u8 data); -int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, - u8 *data, size_t len); -int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, - u8 *data, size_t len); - -int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, - u8 data, u8 mask); - -int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, - int sub); -int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd, - int sub, const void *in, size_t inlen, - size_t size, void *out, size_t outlen); - -static inline int intel_scu_ipc_dev_command(struct intel_scu_ipc_dev *scu, int cmd, - int sub, const void *in, size_t inlen, - void *out, size_t outlen) -{ - return intel_scu_ipc_dev_command_with_size(scu, cmd, sub, in, inlen, - inlen, out, outlen); -} - -#endif diff --git a/arch/x86/include/asm/intel_telemetry.h b/arch/x86/include/asm/intel_telemetry.h index 8046e70dfd7c..43b7657febca 100644 --- a/arch/x86/include/asm/intel_telemetry.h +++ b/arch/x86/include/asm/intel_telemetry.h @@ -10,7 +10,7 @@ #define TELEM_MAX_EVENTS_SRAM 28 #define TELEM_MAX_OS_ALLOCATED_EVENTS 20 -#include +#include enum telemetry_unit { TELEM_PSS = 0, diff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c index f83bbe0acd4a..a8e75f8c14fd 100644 --- a/arch/x86/platform/intel-mid/intel-mid.c +++ b/arch/x86/platform/intel-mid/intel-mid.c @@ -27,9 +27,10 @@ #include #include #include -#include #include +#include + #define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */ #define IPCMSG_COLD_RESET 0xF1 diff --git a/drivers/mfd/intel_pmc_bxt.c b/drivers/mfd/intel_pmc_bxt.c index 9f01d38acc7f..e405d7513ca1 100644 --- a/drivers/mfd/intel_pmc_bxt.c +++ b/drivers/mfd/intel_pmc_bxt.c @@ -23,8 +23,7 @@ #include #include #include - -#include +#include /* Residency with clock rate at 19.2MHz to usecs */ #define S0IX_RESIDENCY_IN_USECS(d, s) \ diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c index ba32cacfc499..ab3c94224dd1 100644 --- a/drivers/mfd/intel_soc_pmic_bxtwc.c +++ b/drivers/mfd/intel_soc_pmic_bxtwc.c @@ -15,8 +15,7 @@ #include #include #include - -#include +#include /* PMIC device registers */ #define REG_ADDR_MASK GENMASK(15, 8) diff --git a/drivers/mfd/intel_soc_pmic_mrfld.c b/drivers/mfd/intel_soc_pmic_mrfld.c index 71da861e8c27..77121775c1a3 100644 --- a/drivers/mfd/intel_soc_pmic_mrfld.c +++ b/drivers/mfd/intel_soc_pmic_mrfld.c @@ -12,11 +12,10 @@ #include #include #include +#include #include #include -#include - /* * Level 2 IRQs * diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index a68df4133403..5b16d29c93d7 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -23,7 +23,7 @@ #include #include -#include +#include /* IPC defines the following message types */ #define IPCMSG_PCNTRL 0xff /* Power controller unit read/write */ diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c index 7d87cbd4b9c6..69b36ce41fa2 100644 --- a/drivers/platform/x86/intel_scu_ipcutil.c +++ b/drivers/platform/x86/intel_scu_ipcutil.c @@ -18,7 +18,7 @@ #include #include -#include +#include static int major; diff --git a/drivers/platform/x86/intel_scu_pcidrv.c b/drivers/platform/x86/intel_scu_pcidrv.c index dbf0310448da..d7f72d6deb44 100644 --- a/drivers/platform/x86/intel_scu_pcidrv.c +++ b/drivers/platform/x86/intel_scu_pcidrv.c @@ -11,7 +11,7 @@ #include #include -#include +#include static int intel_scu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) diff --git a/drivers/platform/x86/intel_scu_pltdrv.c b/drivers/platform/x86/intel_scu_pltdrv.c index 56ec6ae4c824..0892362acd7b 100644 --- a/drivers/platform/x86/intel_scu_pltdrv.c +++ b/drivers/platform/x86/intel_scu_pltdrv.c @@ -15,7 +15,7 @@ #include #include -#include +#include static int intel_scu_platform_probe(struct platform_device *pdev) { diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c index 56989a0d0f43..46b4c5c3a6be 100644 --- a/drivers/usb/typec/mux/intel_pmc_mux.c +++ b/drivers/usb/typec/mux/intel_pmc_mux.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -18,8 +19,6 @@ #include #include -#include - #define PMC_USBC_CMD 0xa7 /* Response status bits */ diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c index 8d71f6a2236b..91c9c3950e44 100644 --- a/drivers/watchdog/intel-mid_wdt.c +++ b/drivers/watchdog/intel-mid_wdt.c @@ -21,8 +21,7 @@ #include #include - -#include +#include #define IPC_WATCHDOG 0xf8 diff --git a/include/linux/platform_data/x86/intel_scu_ipc.h b/include/linux/platform_data/x86/intel_scu_ipc.h new file mode 100644 index 000000000000..0ca9962e97f2 --- /dev/null +++ b/include/linux/platform_data/x86/intel_scu_ipc.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PLATFORM_X86_INTEL_SCU_IPC_H_ +#define __PLATFORM_X86_INTEL_SCU_IPC_H_ + +#include + +struct device; +struct intel_scu_ipc_dev; + +/** + * struct intel_scu_ipc_data - Data used to configure SCU IPC + * @mem: Base address of SCU IPC MMIO registers + * @irq: The IRQ number used for SCU (optional) + */ +struct intel_scu_ipc_data { + struct resource mem; + int irq; +}; + +struct intel_scu_ipc_dev * +__intel_scu_ipc_register(struct device *parent, + const struct intel_scu_ipc_data *scu_data, + struct module *owner); + +#define intel_scu_ipc_register(parent, scu_data) \ + __intel_scu_ipc_register(parent, scu_data, THIS_MODULE) + +void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu); + +struct intel_scu_ipc_dev * +__devm_intel_scu_ipc_register(struct device *parent, + const struct intel_scu_ipc_data *scu_data, + struct module *owner); + +#define devm_intel_scu_ipc_register(parent, scu_data) \ + __devm_intel_scu_ipc_register(parent, scu_data, THIS_MODULE) + +struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void); +void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu); +struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev); + +int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, + u8 *data); +int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, + u8 data); +int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, + u8 *data, size_t len); +int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, + u8 *data, size_t len); + +int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, + u8 data, u8 mask); + +int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, + int sub); +int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd, + int sub, const void *in, size_t inlen, + size_t size, void *out, size_t outlen); + +static inline int intel_scu_ipc_dev_command(struct intel_scu_ipc_dev *scu, int cmd, + int sub, const void *in, size_t inlen, + void *out, size_t outlen) +{ + return intel_scu_ipc_dev_command_with_size(scu, cmd, sub, in, inlen, + inlen, out, outlen); +} + +#endif -- cgit v1.2.3 From 5f1cda51107fd5e53cd012bd1f6f39aede96bdbe Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 9 Sep 2024 15:41:06 +0300 Subject: platform/x86: intel_scu_wdt: Move intel_scu_wdt.h to x86 subfolder This is a platform/x86 library that can only be used on x86 devices. so it makes sense that it lives under the platform_data/x86/ directory instead. No functional changes intended. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240909124952.1152017-4-andriy.shevchenko@linux.intel.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/intel_scu_wdt.c | 3 ++- drivers/watchdog/intel-mid_wdt.c | 2 +- include/linux/platform_data/intel-mid_wdt.h | 19 ------------------- include/linux/platform_data/x86/intel-mid_wdt.h | 19 +++++++++++++++++++ 4 files changed, 22 insertions(+), 21 deletions(-) delete mode 100644 include/linux/platform_data/intel-mid_wdt.h create mode 100644 include/linux/platform_data/x86/intel-mid_wdt.h (limited to 'include/linux/platform_data') diff --git a/drivers/platform/x86/intel_scu_wdt.c b/drivers/platform/x86/intel_scu_wdt.c index d0b6637861d3..746d47d33406 100644 --- a/drivers/platform/x86/intel_scu_wdt.c +++ b/drivers/platform/x86/intel_scu_wdt.c @@ -9,13 +9,14 @@ #include #include #include -#include #include #include #include #include +#include + #define TANGIER_EXT_TIMER0_MSI 12 static struct platform_device wdt_dev = { diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c index 91c9c3950e44..756d262dc580 100644 --- a/drivers/watchdog/intel-mid_wdt.c +++ b/drivers/watchdog/intel-mid_wdt.c @@ -20,7 +20,7 @@ #include #include -#include +#include #include #define IPC_WATCHDOG 0xf8 diff --git a/include/linux/platform_data/intel-mid_wdt.h b/include/linux/platform_data/intel-mid_wdt.h deleted file mode 100644 index 8dba70b4b020..000000000000 --- a/include/linux/platform_data/intel-mid_wdt.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * intel-mid_wdt: generic Intel MID SCU watchdog driver - * - * Copyright (C) 2014 Intel Corporation. All rights reserved. - * Contact: David Cohen - */ - -#ifndef __INTEL_MID_WDT_H__ -#define __INTEL_MID_WDT_H__ - -#include - -struct intel_mid_wdt_pdata { - int irq; - int (*probe)(struct platform_device *pdev); -}; - -#endif /*__INTEL_MID_WDT_H__*/ diff --git a/include/linux/platform_data/x86/intel-mid_wdt.h b/include/linux/platform_data/x86/intel-mid_wdt.h new file mode 100644 index 000000000000..e5c0210d0fec --- /dev/null +++ b/include/linux/platform_data/x86/intel-mid_wdt.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * intel-mid_wdt: generic Intel MID SCU watchdog driver + * + * Copyright (C) 2014 Intel Corporation. All rights reserved. + * Contact: David Cohen + */ + +#ifndef __PLATFORM_X86_INTEL_MID_WDT_H_ +#define __PLATFORM_X86_INTEL_MID_WDT_H_ + +#include + +struct intel_mid_wdt_pdata { + int irq; + int (*probe)(struct platform_device *pdev); +}; + +#endif /* __PLATFORM_X86_INTEL_MID_WDT_H_ */ -- cgit v1.2.3 From 2e7f55ce430240a5547b8a94b4c532fc8c20b18b Mon Sep 17 00:00:00 2001 From: Nikita Shubin Date: Mon, 9 Sep 2024 11:10:34 +0300 Subject: dmaengine: cirrus: Convert to DT for Cirrus EP93xx Convert Cirrus EP93xx DMA to device tree usage: - add OF ID match table with data - add of_probe for device tree - add xlate for m2m/m2p - drop subsys_initcall code - drop platform probe - drop platform structs usage >From now on it only supports device tree probing. Co-developed-by: Alexander Sverdlin Signed-off-by: Alexander Sverdlin Acked-by: Vinod Koul Signed-off-by: Nikita Shubin Tested-by: Alexander Sverdlin Signed-off-by: Arnd Bergmann --- drivers/dma/ep93xx_dma.c | 239 ++++++++++++++++++++++++------- include/linux/platform_data/dma-ep93xx.h | 6 + 2 files changed, 191 insertions(+), 54 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index d6c60635e90d..17c8e2badee2 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -104,6 +106,11 @@ #define DMA_MAX_CHAN_BYTES 0xffff #define DMA_MAX_CHAN_DESCRIPTORS 32 +enum ep93xx_dma_type { + M2P_DMA, + M2M_DMA, +}; + struct ep93xx_dma_engine; static int ep93xx_dma_slave_config_write(struct dma_chan *chan, enum dma_transfer_direction dir, @@ -129,11 +136,17 @@ struct ep93xx_dma_desc { struct list_head node; }; +struct ep93xx_dma_chan_cfg { + u8 port; + enum dma_transfer_direction dir; +}; + /** * struct ep93xx_dma_chan - an EP93xx DMA M2P/M2M channel * @chan: dmaengine API channel * @edma: pointer to the engine device * @regs: memory mapped registers + * @dma_cfg: channel number, direction * @irq: interrupt number of the channel * @clk: clock used by this channel * @tasklet: channel specific tasklet used for callbacks @@ -157,14 +170,12 @@ struct ep93xx_dma_desc { * descriptor in the chain. When a descriptor is moved to the @active queue, * the first and chained descriptors are flattened into a single list. * - * @chan.private holds pointer to &struct ep93xx_dma_data which contains - * necessary channel configuration information. For memcpy channels this must - * be %NULL. */ struct ep93xx_dma_chan { struct dma_chan chan; const struct ep93xx_dma_engine *edma; void __iomem *regs; + struct ep93xx_dma_chan_cfg dma_cfg; int irq; struct clk *clk; struct tasklet_struct tasklet; @@ -216,6 +227,11 @@ struct ep93xx_dma_engine { struct ep93xx_dma_chan channels[] __counted_by(num_channels); }; +struct ep93xx_edma_data { + u32 id; + size_t num_channels; +}; + static inline struct device *chan2dev(struct ep93xx_dma_chan *edmac) { return &edmac->chan.dev->device; @@ -318,10 +334,9 @@ static void m2p_set_control(struct ep93xx_dma_chan *edmac, u32 control) static int m2p_hw_setup(struct ep93xx_dma_chan *edmac) { - struct ep93xx_dma_data *data = edmac->chan.private; u32 control; - writel(data->port & 0xf, edmac->regs + M2P_PPALLOC); + writel(edmac->dma_cfg.port & 0xf, edmac->regs + M2P_PPALLOC); control = M2P_CONTROL_CH_ERROR_INT | M2P_CONTROL_ICE | M2P_CONTROL_ENABLE; @@ -458,16 +473,15 @@ static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac) static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) { - const struct ep93xx_dma_data *data = edmac->chan.private; u32 control = 0; - if (!data) { + if (edmac->dma_cfg.dir == DMA_MEM_TO_MEM) { /* This is memcpy channel, nothing to configure */ writel(control, edmac->regs + M2M_CONTROL); return 0; } - switch (data->port) { + switch (edmac->dma_cfg.port) { case EP93XX_DMA_SSP: /* * This was found via experimenting - anything less than 5 @@ -477,7 +491,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) control = (5 << M2M_CONTROL_PWSC_SHIFT); control |= M2M_CONTROL_NO_HDSK; - if (data->direction == DMA_MEM_TO_DEV) { + if (edmac->dma_cfg.dir == DMA_MEM_TO_DEV) { control |= M2M_CONTROL_DAH; control |= M2M_CONTROL_TM_TX; control |= M2M_CONTROL_RSS_SSPTX; @@ -493,7 +507,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) * This IDE part is totally untested. Values below are taken * from the EP93xx Users's Guide and might not be correct. */ - if (data->direction == DMA_MEM_TO_DEV) { + if (edmac->dma_cfg.dir == DMA_MEM_TO_DEV) { /* Worst case from the UG */ control = (3 << M2M_CONTROL_PWSC_SHIFT); control |= M2M_CONTROL_DAH; @@ -548,7 +562,6 @@ static void m2m_fill_desc(struct ep93xx_dma_chan *edmac) static void m2m_hw_submit(struct ep93xx_dma_chan *edmac) { - struct ep93xx_dma_data *data = edmac->chan.private; u32 control = readl(edmac->regs + M2M_CONTROL); /* @@ -574,7 +587,7 @@ static void m2m_hw_submit(struct ep93xx_dma_chan *edmac) control |= M2M_CONTROL_ENABLE; writel(control, edmac->regs + M2M_CONTROL); - if (!data) { + if (edmac->dma_cfg.dir == DMA_MEM_TO_MEM) { /* * For memcpy channels the software trigger must be asserted * in order to start the memcpy operation. @@ -636,7 +649,7 @@ static int m2m_hw_interrupt(struct ep93xx_dma_chan *edmac) */ if (ep93xx_dma_advance_active(edmac)) { m2m_fill_desc(edmac); - if (done && !edmac->chan.private) { + if (done && edmac->dma_cfg.dir == DMA_MEM_TO_MEM) { /* Software trigger for memcpy channel */ control = readl(edmac->regs + M2M_CONTROL); control |= M2M_CONTROL_START; @@ -867,25 +880,22 @@ static dma_cookie_t ep93xx_dma_tx_submit(struct dma_async_tx_descriptor *tx) static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan) { struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); - struct ep93xx_dma_data *data = chan->private; const char *name = dma_chan_name(chan); int ret, i; /* Sanity check the channel parameters */ if (!edmac->edma->m2m) { - if (!data) - return -EINVAL; - if (data->port < EP93XX_DMA_I2S1 || - data->port > EP93XX_DMA_IRDA) + if (edmac->dma_cfg.port < EP93XX_DMA_I2S1 || + edmac->dma_cfg.port > EP93XX_DMA_IRDA) return -EINVAL; - if (data->direction != ep93xx_dma_chan_direction(chan)) + if (edmac->dma_cfg.dir != ep93xx_dma_chan_direction(chan)) return -EINVAL; } else { - if (data) { - switch (data->port) { + if (edmac->dma_cfg.dir != DMA_MEM_TO_MEM) { + switch (edmac->dma_cfg.port) { case EP93XX_DMA_SSP: case EP93XX_DMA_IDE: - if (!is_slave_direction(data->direction)) + if (!is_slave_direction(edmac->dma_cfg.dir)) return -EINVAL; break; default: @@ -894,9 +904,6 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan) } } - if (data && data->name) - name = data->name; - ret = clk_prepare_enable(edmac->clk); if (ret) return ret; @@ -1315,36 +1322,53 @@ static void ep93xx_dma_issue_pending(struct dma_chan *chan) ep93xx_dma_advance_work(to_ep93xx_dma_chan(chan)); } -static int __init ep93xx_dma_probe(struct platform_device *pdev) +static struct ep93xx_dma_engine *ep93xx_dma_of_probe(struct platform_device *pdev) { - struct ep93xx_dma_platform_data *pdata = dev_get_platdata(&pdev->dev); + const struct ep93xx_edma_data *data; + struct device *dev = &pdev->dev; struct ep93xx_dma_engine *edma; struct dma_device *dma_dev; - int ret, i; + char dma_clk_name[5]; + int i; - edma = kzalloc(struct_size(edma, channels, pdata->num_channels), GFP_KERNEL); + data = device_get_match_data(dev); + if (!data) + return ERR_PTR(dev_err_probe(dev, -ENODEV, "No device match found\n")); + + edma = devm_kzalloc(dev, struct_size(edma, channels, data->num_channels), + GFP_KERNEL); if (!edma) - return -ENOMEM; + return ERR_PTR(-ENOMEM); + edma->m2m = data->id; + edma->num_channels = data->num_channels; dma_dev = &edma->dma_dev; - edma->m2m = platform_get_device_id(pdev)->driver_data; - edma->num_channels = pdata->num_channels; INIT_LIST_HEAD(&dma_dev->channels); - for (i = 0; i < pdata->num_channels; i++) { - const struct ep93xx_dma_chan_data *cdata = &pdata->channels[i]; + for (i = 0; i < edma->num_channels; i++) { struct ep93xx_dma_chan *edmac = &edma->channels[i]; edmac->chan.device = dma_dev; - edmac->regs = cdata->base; - edmac->irq = cdata->irq; + edmac->regs = devm_platform_ioremap_resource(pdev, i); + if (IS_ERR(edmac->regs)) + return edmac->regs; + + edmac->irq = fwnode_irq_get(dev_fwnode(dev), i); + if (edmac->irq < 0) + return ERR_PTR(edmac->irq); + edmac->edma = edma; - edmac->clk = clk_get(NULL, cdata->name); + if (edma->m2m) + sprintf(dma_clk_name, "m2m%u", i); + else + sprintf(dma_clk_name, "m2p%u", i); + + edmac->clk = devm_clk_get(dev, dma_clk_name); if (IS_ERR(edmac->clk)) { - dev_warn(&pdev->dev, "failed to get clock for %s\n", - cdata->name); - continue; + dev_err_probe(dev, PTR_ERR(edmac->clk), + "no %s clock found\n", dma_clk_name); + return ERR_CAST(edmac->clk); } spin_lock_init(&edmac->lock); @@ -1357,6 +1381,90 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev) &dma_dev->channels); } + return edma; +} + +static bool ep93xx_m2p_dma_filter(struct dma_chan *chan, void *filter_param) +{ + struct ep93xx_dma_chan *echan = to_ep93xx_dma_chan(chan); + struct ep93xx_dma_chan_cfg *cfg = filter_param; + + if (cfg->dir != ep93xx_dma_chan_direction(chan)) + return false; + + echan->dma_cfg = *cfg; + return true; +} + +static struct dma_chan *ep93xx_m2p_dma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct ep93xx_dma_engine *edma = ofdma->of_dma_data; + dma_cap_mask_t mask = edma->dma_dev.cap_mask; + struct ep93xx_dma_chan_cfg dma_cfg; + u8 port = dma_spec->args[0]; + u8 direction = dma_spec->args[1]; + + if (port > EP93XX_DMA_IRDA) + return NULL; + + if (!is_slave_direction(direction)) + return NULL; + + dma_cfg.port = port; + dma_cfg.dir = direction; + + return __dma_request_channel(&mask, ep93xx_m2p_dma_filter, &dma_cfg, ofdma->of_node); +} + +static bool ep93xx_m2m_dma_filter(struct dma_chan *chan, void *filter_param) +{ + struct ep93xx_dma_chan *echan = to_ep93xx_dma_chan(chan); + struct ep93xx_dma_chan_cfg *cfg = filter_param; + + echan->dma_cfg = *cfg; + + return true; +} + +static struct dma_chan *ep93xx_m2m_dma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct ep93xx_dma_engine *edma = ofdma->of_dma_data; + dma_cap_mask_t mask = edma->dma_dev.cap_mask; + struct ep93xx_dma_chan_cfg dma_cfg; + u8 port = dma_spec->args[0]; + u8 direction = dma_spec->args[1]; + + if (!is_slave_direction(direction)) + return NULL; + + switch (port) { + case EP93XX_DMA_SSP: + case EP93XX_DMA_IDE: + break; + default: + return NULL; + } + + dma_cfg.port = port; + dma_cfg.dir = direction; + + return __dma_request_channel(&mask, ep93xx_m2m_dma_filter, &dma_cfg, ofdma->of_node); +} + +static int ep93xx_dma_probe(struct platform_device *pdev) +{ + struct ep93xx_dma_engine *edma; + struct dma_device *dma_dev; + int ret; + + edma = ep93xx_dma_of_probe(pdev); + if (!edma) + return PTR_ERR(edma); + + dma_dev = &edma->dma_dev; + dma_cap_zero(dma_dev->cap_mask); dma_cap_set(DMA_SLAVE, dma_dev->cap_mask); dma_cap_set(DMA_CYCLIC, dma_dev->cap_mask); @@ -1393,21 +1501,46 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev) } ret = dma_async_device_register(dma_dev); - if (unlikely(ret)) { - for (i = 0; i < edma->num_channels; i++) { - struct ep93xx_dma_chan *edmac = &edma->channels[i]; - if (!IS_ERR_OR_NULL(edmac->clk)) - clk_put(edmac->clk); - } - kfree(edma); + if (ret) + return ret; + + if (edma->m2m) { + ret = of_dma_controller_register(pdev->dev.of_node, ep93xx_m2m_dma_of_xlate, + edma); } else { - dev_info(dma_dev->dev, "EP93xx M2%s DMA ready\n", - edma->m2m ? "M" : "P"); + ret = of_dma_controller_register(pdev->dev.of_node, ep93xx_m2p_dma_of_xlate, + edma); } + if (ret) + goto err_dma_unregister; + + dev_info(dma_dev->dev, "EP93xx M2%s DMA ready\n", edma->m2m ? "M" : "P"); + + return 0; + +err_dma_unregister: + dma_async_device_unregister(dma_dev); return ret; } +static const struct ep93xx_edma_data edma_m2p = { + .id = M2P_DMA, + .num_channels = 10, +}; + +static const struct ep93xx_edma_data edma_m2m = { + .id = M2M_DMA, + .num_channels = 2, +}; + +static const struct of_device_id ep93xx_dma_of_ids[] = { + { .compatible = "cirrus,ep9301-dma-m2p", .data = &edma_m2p }, + { .compatible = "cirrus,ep9301-dma-m2m", .data = &edma_m2m }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ep93xx_dma_of_ids); + static const struct platform_device_id ep93xx_dma_driver_ids[] = { { "ep93xx-dma-m2p", 0 }, { "ep93xx-dma-m2m", 1 }, @@ -1417,15 +1550,13 @@ static const struct platform_device_id ep93xx_dma_driver_ids[] = { static struct platform_driver ep93xx_dma_driver = { .driver = { .name = "ep93xx-dma", + .of_match_table = ep93xx_dma_of_ids, }, .id_table = ep93xx_dma_driver_ids, + .probe = ep93xx_dma_probe, }; -static int __init ep93xx_dma_module_init(void) -{ - return platform_driver_probe(&ep93xx_dma_driver, ep93xx_dma_probe); -} -subsys_initcall(ep93xx_dma_module_init); +module_platform_driver(ep93xx_dma_driver); MODULE_AUTHOR("Mika Westerberg "); MODULE_DESCRIPTION("EP93xx DMA driver"); diff --git a/include/linux/platform_data/dma-ep93xx.h b/include/linux/platform_data/dma-ep93xx.h index eb9805bb3fe8..9ec5cdd5a1eb 100644 --- a/include/linux/platform_data/dma-ep93xx.h +++ b/include/linux/platform_data/dma-ep93xx.h @@ -3,8 +3,11 @@ #define __ASM_ARCH_DMA_H #include +#include #include #include +#include +#include /* * M2P channels. @@ -70,6 +73,9 @@ struct ep93xx_dma_platform_data { static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan) { + if (device_is_compatible(chan->device->dev, "cirrus,ep9301-dma-m2p")) + return true; + return !strcmp(dev_name(chan->device->dev), "ep93xx-dma-m2p"); } -- cgit v1.2.3 From e5ef574dda702e62081d5c7991949cbdb7f65c08 Mon Sep 17 00:00:00 2001 From: Nikita Shubin Date: Mon, 9 Sep 2024 11:11:00 +0300 Subject: ARM: ep93xx: delete all boardfiles Delete the ep93xx board files. Signed-off-by: Nikita Shubin Tested-by: Alexander Sverdlin Acked-by: Vinod Koul Signed-off-by: Arnd Bergmann --- arch/arm/mach-ep93xx/clock.c | 733 ------------------------ arch/arm/mach-ep93xx/core.c | 955 ------------------------------- arch/arm/mach-ep93xx/dma.c | 114 ---- arch/arm/mach-ep93xx/edb93xx.c | 368 ------------ arch/arm/mach-ep93xx/ep93xx-regs.h | 38 -- arch/arm/mach-ep93xx/gpio-ep93xx.h | 111 ---- arch/arm/mach-ep93xx/hardware.h | 25 - arch/arm/mach-ep93xx/irqs.h | 76 --- arch/arm/mach-ep93xx/platform.h | 42 -- arch/arm/mach-ep93xx/soc.h | 212 ------- arch/arm/mach-ep93xx/timer-ep93xx.c | 143 ----- arch/arm/mach-ep93xx/ts72xx.c | 422 -------------- arch/arm/mach-ep93xx/ts72xx.h | 94 --- arch/arm/mach-ep93xx/vision_ep9307.c | 321 ----------- include/linux/platform_data/spi-ep93xx.h | 15 - 15 files changed, 3669 deletions(-) delete mode 100644 arch/arm/mach-ep93xx/clock.c delete mode 100644 arch/arm/mach-ep93xx/core.c delete mode 100644 arch/arm/mach-ep93xx/dma.c delete mode 100644 arch/arm/mach-ep93xx/edb93xx.c delete mode 100644 arch/arm/mach-ep93xx/ep93xx-regs.h delete mode 100644 arch/arm/mach-ep93xx/gpio-ep93xx.h delete mode 100644 arch/arm/mach-ep93xx/hardware.h delete mode 100644 arch/arm/mach-ep93xx/irqs.h delete mode 100644 arch/arm/mach-ep93xx/platform.h delete mode 100644 arch/arm/mach-ep93xx/soc.h delete mode 100644 arch/arm/mach-ep93xx/timer-ep93xx.c delete mode 100644 arch/arm/mach-ep93xx/ts72xx.c delete mode 100644 arch/arm/mach-ep93xx/ts72xx.h delete mode 100644 arch/arm/mach-ep93xx/vision_ep9307.c delete mode 100644 include/linux/platform_data/spi-ep93xx.h (limited to 'include/linux/platform_data') diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c deleted file mode 100644 index e9f72a529b50..000000000000 --- a/arch/arm/mach-ep93xx/clock.c +++ /dev/null @@ -1,733 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/clock.c - * Clock control for Cirrus EP93xx chips. - * - * Copyright (C) 2006 Lennert Buytenhek - */ - -#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hardware.h" - -#include - -#include "soc.h" - -static DEFINE_SPINLOCK(clk_lock); - -static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; -static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; -static char pclk_divisors[] = { 1, 2, 4, 8 }; - -static char adc_divisors[] = { 16, 4 }; -static char sclk_divisors[] = { 2, 4 }; -static char lrclk_divisors[] = { 32, 64, 128 }; - -static const char * const mux_parents[] = { - "xtali", - "pll1", - "pll2" -}; - -/* - * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS - */ -static unsigned long calc_pll_rate(unsigned long long rate, u32 config_word) -{ - int i; - - rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */ - rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */ - do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */ - for (i = 0; i < ((config_word >> 16) & 3); i++) /* PS */ - rate >>= 1; - - return (unsigned long)rate; -} - -struct clk_psc { - struct clk_hw hw; - void __iomem *reg; - u8 bit_idx; - u32 mask; - u8 shift; - u8 width; - char *div; - u8 num_div; - spinlock_t *lock; -}; - -#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw) - -static int ep93xx_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_psc *psc = to_clk_psc(hw); - u32 val = readl(psc->reg); - - return (val & BIT(psc->bit_idx)) ? 1 : 0; -} - -static int ep93xx_clk_enable(struct clk_hw *hw) -{ - struct clk_psc *psc = to_clk_psc(hw); - unsigned long flags = 0; - u32 val; - - if (psc->lock) - spin_lock_irqsave(psc->lock, flags); - - val = __raw_readl(psc->reg); - val |= BIT(psc->bit_idx); - - ep93xx_syscon_swlocked_write(val, psc->reg); - - if (psc->lock) - spin_unlock_irqrestore(psc->lock, flags); - - return 0; -} - -static void ep93xx_clk_disable(struct clk_hw *hw) -{ - struct clk_psc *psc = to_clk_psc(hw); - unsigned long flags = 0; - u32 val; - - if (psc->lock) - spin_lock_irqsave(psc->lock, flags); - - val = __raw_readl(psc->reg); - val &= ~BIT(psc->bit_idx); - - ep93xx_syscon_swlocked_write(val, psc->reg); - - if (psc->lock) - spin_unlock_irqrestore(psc->lock, flags); -} - -static const struct clk_ops clk_ep93xx_gate_ops = { - .enable = ep93xx_clk_enable, - .disable = ep93xx_clk_disable, - .is_enabled = ep93xx_clk_is_enabled, -}; - -static struct clk_hw *ep93xx_clk_register_gate(const char *name, - const char *parent_name, - void __iomem *reg, - u8 bit_idx) -{ - struct clk_init_data init; - struct clk_psc *psc; - struct clk *clk; - - psc = kzalloc(sizeof(*psc), GFP_KERNEL); - if (!psc) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &clk_ep93xx_gate_ops; - init.flags = CLK_SET_RATE_PARENT; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = (parent_name ? 1 : 0); - - psc->reg = reg; - psc->bit_idx = bit_idx; - psc->hw.init = &init; - psc->lock = &clk_lock; - - clk = clk_register(NULL, &psc->hw); - if (IS_ERR(clk)) { - kfree(psc); - return ERR_CAST(clk); - } - - return &psc->hw; -} - -static u8 ep93xx_mux_get_parent(struct clk_hw *hw) -{ - struct clk_psc *psc = to_clk_psc(hw); - u32 val = __raw_readl(psc->reg); - - if (!(val & EP93XX_SYSCON_CLKDIV_ESEL)) - return 0; - - if (!(val & EP93XX_SYSCON_CLKDIV_PSEL)) - return 1; - - return 2; -} - -static int ep93xx_mux_set_parent_lock(struct clk_hw *hw, u8 index) -{ - struct clk_psc *psc = to_clk_psc(hw); - unsigned long flags = 0; - u32 val; - - if (index >= ARRAY_SIZE(mux_parents)) - return -EINVAL; - - if (psc->lock) - spin_lock_irqsave(psc->lock, flags); - - val = __raw_readl(psc->reg); - val &= ~(EP93XX_SYSCON_CLKDIV_ESEL | EP93XX_SYSCON_CLKDIV_PSEL); - - - if (index != 0) { - val |= EP93XX_SYSCON_CLKDIV_ESEL; - val |= (index - 1) ? EP93XX_SYSCON_CLKDIV_PSEL : 0; - } - - ep93xx_syscon_swlocked_write(val, psc->reg); - - if (psc->lock) - spin_unlock_irqrestore(psc->lock, flags); - - return 0; -} - -static bool is_best(unsigned long rate, unsigned long now, - unsigned long best) -{ - return abs(rate - now) < abs(rate - best); -} - -static int ep93xx_mux_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - unsigned long rate = req->rate; - struct clk *best_parent = NULL; - unsigned long __parent_rate; - unsigned long best_rate = 0, actual_rate, mclk_rate; - unsigned long best_parent_rate; - int __div = 0, __pdiv = 0; - int i; - - /* - * Try the two pll's and the external clock - * Because the valid predividers are 2, 2.5 and 3, we multiply - * all the clocks by 2 to avoid floating point math. - * - * This is based on the algorithm in the ep93xx raster guide: - * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf - * - */ - for (i = 0; i < ARRAY_SIZE(mux_parents); i++) { - struct clk *parent = clk_get_sys(mux_parents[i], NULL); - - __parent_rate = clk_get_rate(parent); - mclk_rate = __parent_rate * 2; - - /* Try each predivider value */ - for (__pdiv = 4; __pdiv <= 6; __pdiv++) { - __div = mclk_rate / (rate * __pdiv); - if (__div < 2 || __div > 127) - continue; - - actual_rate = mclk_rate / (__pdiv * __div); - if (is_best(rate, actual_rate, best_rate)) { - best_rate = actual_rate; - best_parent_rate = __parent_rate; - best_parent = parent; - } - } - } - - if (!best_parent) - return -EINVAL; - - req->best_parent_rate = best_parent_rate; - req->best_parent_hw = __clk_get_hw(best_parent); - req->rate = best_rate; - - return 0; -} - -static unsigned long ep93xx_ddiv_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_psc *psc = to_clk_psc(hw); - unsigned long rate = 0; - u32 val = __raw_readl(psc->reg); - int __pdiv = ((val >> EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) & 0x03); - int __div = val & 0x7f; - - if (__div > 0) - rate = (parent_rate * 2) / ((__pdiv + 3) * __div); - - return rate; -} - -static int ep93xx_ddiv_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_psc *psc = to_clk_psc(hw); - int pdiv = 0, div = 0; - unsigned long best_rate = 0, actual_rate, mclk_rate; - int __div = 0, __pdiv = 0; - u32 val; - - mclk_rate = parent_rate * 2; - - for (__pdiv = 4; __pdiv <= 6; __pdiv++) { - __div = mclk_rate / (rate * __pdiv); - if (__div < 2 || __div > 127) - continue; - - actual_rate = mclk_rate / (__pdiv * __div); - if (is_best(rate, actual_rate, best_rate)) { - pdiv = __pdiv - 3; - div = __div; - best_rate = actual_rate; - } - } - - if (!best_rate) - return -EINVAL; - - val = __raw_readl(psc->reg); - - /* Clear old dividers */ - val &= ~0x37f; - - /* Set the new pdiv and div bits for the new clock rate */ - val |= (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div; - ep93xx_syscon_swlocked_write(val, psc->reg); - - return 0; -} - -static const struct clk_ops clk_ddiv_ops = { - .enable = ep93xx_clk_enable, - .disable = ep93xx_clk_disable, - .is_enabled = ep93xx_clk_is_enabled, - .get_parent = ep93xx_mux_get_parent, - .set_parent = ep93xx_mux_set_parent_lock, - .determine_rate = ep93xx_mux_determine_rate, - .recalc_rate = ep93xx_ddiv_recalc_rate, - .set_rate = ep93xx_ddiv_set_rate, -}; - -static struct clk_hw *clk_hw_register_ddiv(const char *name, - void __iomem *reg, - u8 bit_idx) -{ - struct clk_init_data init; - struct clk_psc *psc; - struct clk *clk; - - psc = kzalloc(sizeof(*psc), GFP_KERNEL); - if (!psc) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &clk_ddiv_ops; - init.flags = 0; - init.parent_names = mux_parents; - init.num_parents = ARRAY_SIZE(mux_parents); - - psc->reg = reg; - psc->bit_idx = bit_idx; - psc->lock = &clk_lock; - psc->hw.init = &init; - - clk = clk_register(NULL, &psc->hw); - if (IS_ERR(clk)) { - kfree(psc); - return ERR_CAST(clk); - } - return &psc->hw; -} - -static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_psc *psc = to_clk_psc(hw); - u32 val = __raw_readl(psc->reg); - u8 index = (val & psc->mask) >> psc->shift; - - if (index >= psc->num_div) - return 0; - - return DIV_ROUND_UP_ULL(parent_rate, psc->div[index]); -} - -static long ep93xx_div_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - struct clk_psc *psc = to_clk_psc(hw); - unsigned long best = 0, now, maxdiv; - int i; - - maxdiv = psc->div[psc->num_div - 1]; - - for (i = 0; i < psc->num_div; i++) { - if ((rate * psc->div[i]) == *parent_rate) - return DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]); - - now = DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]); - - if (is_best(rate, now, best)) - best = now; - } - - if (!best) - best = DIV_ROUND_UP_ULL(*parent_rate, maxdiv); - - return best; -} - -static int ep93xx_div_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_psc *psc = to_clk_psc(hw); - u32 val = __raw_readl(psc->reg) & ~psc->mask; - int i; - - for (i = 0; i < psc->num_div; i++) - if (rate == parent_rate / psc->div[i]) { - val |= i << psc->shift; - break; - } - - if (i == psc->num_div) - return -EINVAL; - - ep93xx_syscon_swlocked_write(val, psc->reg); - - return 0; -} - -static const struct clk_ops ep93xx_div_ops = { - .enable = ep93xx_clk_enable, - .disable = ep93xx_clk_disable, - .is_enabled = ep93xx_clk_is_enabled, - .recalc_rate = ep93xx_div_recalc_rate, - .round_rate = ep93xx_div_round_rate, - .set_rate = ep93xx_div_set_rate, -}; - -static struct clk_hw *clk_hw_register_div(const char *name, - const char *parent_name, - void __iomem *reg, - u8 enable_bit, - u8 shift, - u8 width, - char *clk_divisors, - u8 num_div) -{ - struct clk_init_data init; - struct clk_psc *psc; - struct clk *clk; - - psc = kzalloc(sizeof(*psc), GFP_KERNEL); - if (!psc) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &ep93xx_div_ops; - init.flags = 0; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = 1; - - psc->reg = reg; - psc->bit_idx = enable_bit; - psc->mask = GENMASK(shift + width - 1, shift); - psc->shift = shift; - psc->div = clk_divisors; - psc->num_div = num_div; - psc->lock = &clk_lock; - psc->hw.init = &init; - - clk = clk_register(NULL, &psc->hw); - if (IS_ERR(clk)) { - kfree(psc); - return ERR_CAST(clk); - } - return &psc->hw; -} - -struct ep93xx_gate { - unsigned int bit; - const char *dev_id; - const char *con_id; -}; - -static struct ep93xx_gate ep93xx_uarts[] = { - {EP93XX_SYSCON_DEVCFG_U1EN, "apb:uart1", NULL}, - {EP93XX_SYSCON_DEVCFG_U2EN, "apb:uart2", NULL}, - {EP93XX_SYSCON_DEVCFG_U3EN, "apb:uart3", NULL}, -}; - -static void __init ep93xx_uart_clock_init(void) -{ - unsigned int i; - struct clk_hw *hw; - u32 value; - unsigned int clk_uart_div; - - value = __raw_readl(EP93XX_SYSCON_PWRCNT); - if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD) - clk_uart_div = 1; - else - clk_uart_div = 2; - - hw = clk_hw_register_fixed_factor(NULL, "uart", "xtali", 0, 1, clk_uart_div); - - /* parenting uart gate clocks to uart clock */ - for (i = 0; i < ARRAY_SIZE(ep93xx_uarts); i++) { - hw = ep93xx_clk_register_gate(ep93xx_uarts[i].dev_id, - "uart", - EP93XX_SYSCON_DEVCFG, - ep93xx_uarts[i].bit); - - clk_hw_register_clkdev(hw, NULL, ep93xx_uarts[i].dev_id); - } -} - -static struct ep93xx_gate ep93xx_dmas[] = { - {EP93XX_SYSCON_PWRCNT_DMA_M2P0, NULL, "m2p0"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P1, NULL, "m2p1"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P2, NULL, "m2p2"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P3, NULL, "m2p3"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P4, NULL, "m2p4"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P5, NULL, "m2p5"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P6, NULL, "m2p6"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P7, NULL, "m2p7"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P8, NULL, "m2p8"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P9, NULL, "m2p9"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2M0, NULL, "m2m0"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2M1, NULL, "m2m1"}, -}; - -static void __init ep93xx_dma_clock_init(void) -{ - unsigned int i; - struct clk_hw *hw; - int ret; - - for (i = 0; i < ARRAY_SIZE(ep93xx_dmas); i++) { - hw = clk_hw_register_gate(NULL, ep93xx_dmas[i].con_id, - "hclk", 0, - EP93XX_SYSCON_PWRCNT, - ep93xx_dmas[i].bit, - 0, - &clk_lock); - - ret = clk_hw_register_clkdev(hw, ep93xx_dmas[i].con_id, NULL); - if (ret) - pr_err("%s: failed to register lookup %s\n", - __func__, ep93xx_dmas[i].con_id); - } -} - -static int __init ep93xx_clock_init(void) -{ - u32 value; - struct clk_hw *hw; - unsigned long clk_pll1_rate; - unsigned long clk_f_rate; - unsigned long clk_h_rate; - unsigned long clk_p_rate; - unsigned long clk_pll2_rate; - unsigned int clk_f_div; - unsigned int clk_h_div; - unsigned int clk_p_div; - unsigned int clk_usb_div; - unsigned long clk_spi_div; - - hw = clk_hw_register_fixed_rate(NULL, "xtali", NULL, 0, EP93XX_EXT_CLK_RATE); - clk_hw_register_clkdev(hw, NULL, "xtali"); - - /* Determine the bootloader configured pll1 rate */ - value = __raw_readl(EP93XX_SYSCON_CLKSET1); - if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1)) - clk_pll1_rate = EP93XX_EXT_CLK_RATE; - else - clk_pll1_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value); - - hw = clk_hw_register_fixed_rate(NULL, "pll1", "xtali", 0, clk_pll1_rate); - clk_hw_register_clkdev(hw, NULL, "pll1"); - - /* Initialize the pll1 derived clocks */ - clk_f_div = fclk_divisors[(value >> 25) & 0x7]; - clk_h_div = hclk_divisors[(value >> 20) & 0x7]; - clk_p_div = pclk_divisors[(value >> 18) & 0x3]; - - hw = clk_hw_register_fixed_factor(NULL, "fclk", "pll1", 0, 1, clk_f_div); - clk_f_rate = clk_get_rate(hw->clk); - hw = clk_hw_register_fixed_factor(NULL, "hclk", "pll1", 0, 1, clk_h_div); - clk_h_rate = clk_get_rate(hw->clk); - hw = clk_hw_register_fixed_factor(NULL, "pclk", "hclk", 0, 1, clk_p_div); - clk_p_rate = clk_get_rate(hw->clk); - - clk_hw_register_clkdev(hw, "apb_pclk", NULL); - - ep93xx_dma_clock_init(); - - /* Determine the bootloader configured pll2 rate */ - value = __raw_readl(EP93XX_SYSCON_CLKSET2); - if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2)) - clk_pll2_rate = EP93XX_EXT_CLK_RATE; - else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN) - clk_pll2_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value); - else - clk_pll2_rate = 0; - - hw = clk_hw_register_fixed_rate(NULL, "pll2", "xtali", 0, clk_pll2_rate); - clk_hw_register_clkdev(hw, NULL, "pll2"); - - /* Initialize the pll2 derived clocks */ - /* - * These four bits set the divide ratio between the PLL2 - * output and the USB clock. - * 0000 - Divide by 1 - * 0001 - Divide by 2 - * 0010 - Divide by 3 - * 0011 - Divide by 4 - * 0100 - Divide by 5 - * 0101 - Divide by 6 - * 0110 - Divide by 7 - * 0111 - Divide by 8 - * 1000 - Divide by 9 - * 1001 - Divide by 10 - * 1010 - Divide by 11 - * 1011 - Divide by 12 - * 1100 - Divide by 13 - * 1101 - Divide by 14 - * 1110 - Divide by 15 - * 1111 - Divide by 1 - * On power-on-reset these bits are reset to 0000b. - */ - clk_usb_div = (((value >> 28) & 0xf) + 1); - hw = clk_hw_register_fixed_factor(NULL, "usb_clk", "pll2", 0, 1, clk_usb_div); - hw = clk_hw_register_gate(NULL, "ohci-platform", - "usb_clk", 0, - EP93XX_SYSCON_PWRCNT, - EP93XX_SYSCON_PWRCNT_USH_EN, - 0, - &clk_lock); - clk_hw_register_clkdev(hw, NULL, "ohci-platform"); - - /* - * EP93xx SSP clock rate was doubled in version E2. For more information - * see: - * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf - */ - clk_spi_div = 1; - if (ep93xx_chip_revision() < EP93XX_CHIP_REV_E2) - clk_spi_div = 2; - hw = clk_hw_register_fixed_factor(NULL, "ep93xx-spi.0", "xtali", 0, 1, clk_spi_div); - clk_hw_register_clkdev(hw, NULL, "ep93xx-spi.0"); - - /* pwm clock */ - hw = clk_hw_register_fixed_factor(NULL, "pwm_clk", "xtali", 0, 1, 1); - clk_hw_register_clkdev(hw, "pwm_clk", NULL); - - pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n", - clk_pll1_rate / 1000000, clk_pll2_rate / 1000000); - pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n", - clk_f_rate / 1000000, clk_h_rate / 1000000, - clk_p_rate / 1000000); - - ep93xx_uart_clock_init(); - - /* touchscreen/adc clock */ - hw = clk_hw_register_div("ep93xx-adc", - "xtali", - EP93XX_SYSCON_KEYTCHCLKDIV, - EP93XX_SYSCON_KEYTCHCLKDIV_TSEN, - EP93XX_SYSCON_KEYTCHCLKDIV_ADIV, - 1, - adc_divisors, - ARRAY_SIZE(adc_divisors)); - - clk_hw_register_clkdev(hw, NULL, "ep93xx-adc"); - - /* keypad clock */ - hw = clk_hw_register_div("ep93xx-keypad", - "xtali", - EP93XX_SYSCON_KEYTCHCLKDIV, - EP93XX_SYSCON_KEYTCHCLKDIV_KEN, - EP93XX_SYSCON_KEYTCHCLKDIV_KDIV, - 1, - adc_divisors, - ARRAY_SIZE(adc_divisors)); - - clk_hw_register_clkdev(hw, NULL, "ep93xx-keypad"); - - /* On reset PDIV and VDIV is set to zero, while PDIV zero - * means clock disable, VDIV shouldn't be zero. - * So i set both dividers to minimum. - */ - /* ENA - Enable CLK divider. */ - /* PDIV - 00 - Disable clock */ - /* VDIV - at least 2 */ - /* Check and enable video clk registers */ - value = __raw_readl(EP93XX_SYSCON_VIDCLKDIV); - value |= (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2; - ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_VIDCLKDIV); - - /* check and enable i2s clk registers */ - value = __raw_readl(EP93XX_SYSCON_I2SCLKDIV); - value |= (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2; - ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_I2SCLKDIV); - - /* video clk */ - hw = clk_hw_register_ddiv("ep93xx-fb", - EP93XX_SYSCON_VIDCLKDIV, - EP93XX_SYSCON_CLKDIV_ENABLE); - - clk_hw_register_clkdev(hw, NULL, "ep93xx-fb"); - - /* i2s clk */ - hw = clk_hw_register_ddiv("mclk", - EP93XX_SYSCON_I2SCLKDIV, - EP93XX_SYSCON_CLKDIV_ENABLE); - - clk_hw_register_clkdev(hw, "mclk", "ep93xx-i2s"); - - /* i2s sclk */ -#define EP93XX_I2SCLKDIV_SDIV_SHIFT 16 -#define EP93XX_I2SCLKDIV_SDIV_WIDTH 1 - hw = clk_hw_register_div("sclk", - "mclk", - EP93XX_SYSCON_I2SCLKDIV, - EP93XX_SYSCON_I2SCLKDIV_SENA, - EP93XX_I2SCLKDIV_SDIV_SHIFT, - EP93XX_I2SCLKDIV_SDIV_WIDTH, - sclk_divisors, - ARRAY_SIZE(sclk_divisors)); - - clk_hw_register_clkdev(hw, "sclk", "ep93xx-i2s"); - - /* i2s lrclk */ -#define EP93XX_I2SCLKDIV_LRDIV32_SHIFT 17 -#define EP93XX_I2SCLKDIV_LRDIV32_WIDTH 3 - hw = clk_hw_register_div("lrclk", - "sclk", - EP93XX_SYSCON_I2SCLKDIV, - EP93XX_SYSCON_I2SCLKDIV_SENA, - EP93XX_I2SCLKDIV_LRDIV32_SHIFT, - EP93XX_I2SCLKDIV_LRDIV32_WIDTH, - lrclk_divisors, - ARRAY_SIZE(lrclk_divisors)); - - clk_hw_register_clkdev(hw, "lrclk", "ep93xx-i2s"); - - return 0; -} -postcore_initcall(ep93xx_clock_init); diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c deleted file mode 100644 index 9c6154bb37b5..000000000000 --- a/arch/arm/mach-ep93xx/core.c +++ /dev/null @@ -1,955 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/core.c - * Core routines for Cirrus EP93xx chips. - * - * Copyright (C) 2006 Lennert Buytenhek - * Copyright (C) 2007 Herbert Valerio Riedel - * - * Thanks go to Michael Burian and Ray Lehtiniemi for their key - * role in the ep93xx linux community. - */ - -#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hardware.h" -#include -#include -#include -#include - -#include "gpio-ep93xx.h" - -#include -#include - -#include "soc.h" -#include "irqs.h" - -/************************************************************************* - * Static I/O mappings that are needed for all EP93xx platforms - *************************************************************************/ -static struct map_desc ep93xx_io_desc[] __initdata = { - { - .virtual = EP93XX_AHB_VIRT_BASE, - .pfn = __phys_to_pfn(EP93XX_AHB_PHYS_BASE), - .length = EP93XX_AHB_SIZE, - .type = MT_DEVICE, - }, { - .virtual = EP93XX_APB_VIRT_BASE, - .pfn = __phys_to_pfn(EP93XX_APB_PHYS_BASE), - .length = EP93XX_APB_SIZE, - .type = MT_DEVICE, - }, -}; - -void __init ep93xx_map_io(void) -{ - iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc)); -} - -/************************************************************************* - * EP93xx IRQ handling - *************************************************************************/ -void __init ep93xx_init_irq(void) -{ - vic_init(EP93XX_VIC1_BASE, IRQ_EP93XX_VIC0, EP93XX_VIC1_VALID_IRQ_MASK, 0); - vic_init(EP93XX_VIC2_BASE, IRQ_EP93XX_VIC1, EP93XX_VIC2_VALID_IRQ_MASK, 0); -} - - -/************************************************************************* - * EP93xx System Controller Software Locked register handling - *************************************************************************/ - -/* - * syscon_swlock prevents anything else from writing to the syscon - * block while a software locked register is being written. - */ -static DEFINE_SPINLOCK(syscon_swlock); - -void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg) -{ - unsigned long flags; - - spin_lock_irqsave(&syscon_swlock, flags); - - __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); - __raw_writel(val, reg); - - spin_unlock_irqrestore(&syscon_swlock, flags); -} - -void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&syscon_swlock, flags); - - val = __raw_readl(EP93XX_SYSCON_DEVCFG); - val &= ~clear_bits; - val |= set_bits; - __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); - __raw_writel(val, EP93XX_SYSCON_DEVCFG); - - spin_unlock_irqrestore(&syscon_swlock, flags); -} - -/** - * ep93xx_chip_revision() - returns the EP93xx chip revision - * - * See "platform.h" for more information. - */ -unsigned int ep93xx_chip_revision(void) -{ - unsigned int v; - - v = __raw_readl(EP93XX_SYSCON_SYSCFG); - v &= EP93XX_SYSCON_SYSCFG_REV_MASK; - v >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT; - return v; -} -EXPORT_SYMBOL_GPL(ep93xx_chip_revision); - -/************************************************************************* - * EP93xx GPIO - *************************************************************************/ -/* port A */ -static struct resource ep93xx_a_gpio_resources[] = { - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE, 0x04, "data"), - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x10, 0x04, "dir"), - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x90, 0x1c, "intr"), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO_AB), -}; - -static struct platform_device ep93xx_a_gpio = { - .name = "gpio-ep93xx", - .id = 0, - .num_resources = ARRAY_SIZE(ep93xx_a_gpio_resources), - .resource = ep93xx_a_gpio_resources, -}; - -/* port B */ -static struct resource ep93xx_b_gpio_resources[] = { - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x04, 0x04, "data"), - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x14, 0x04, "dir"), - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0xac, 0x1c, "intr"), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO_AB), -}; - -static struct platform_device ep93xx_b_gpio = { - .name = "gpio-ep93xx", - .id = 1, - .num_resources = ARRAY_SIZE(ep93xx_b_gpio_resources), - .resource = ep93xx_b_gpio_resources, -}; - -/* port C */ -static struct resource ep93xx_c_gpio_resources[] = { - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x08, 0x04, "data"), - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x18, 0x04, "dir"), -}; - -static struct platform_device ep93xx_c_gpio = { - .name = "gpio-ep93xx", - .id = 2, - .num_resources = ARRAY_SIZE(ep93xx_c_gpio_resources), - .resource = ep93xx_c_gpio_resources, -}; - -/* port D */ -static struct resource ep93xx_d_gpio_resources[] = { - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x0c, 0x04, "data"), - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x1c, 0x04, "dir"), -}; - -static struct platform_device ep93xx_d_gpio = { - .name = "gpio-ep93xx", - .id = 3, - .num_resources = ARRAY_SIZE(ep93xx_d_gpio_resources), - .resource = ep93xx_d_gpio_resources, -}; - -/* port E */ -static struct resource ep93xx_e_gpio_resources[] = { - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x20, 0x04, "data"), - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x24, 0x04, "dir"), -}; - -static struct platform_device ep93xx_e_gpio = { - .name = "gpio-ep93xx", - .id = 4, - .num_resources = ARRAY_SIZE(ep93xx_e_gpio_resources), - .resource = ep93xx_e_gpio_resources, -}; - -/* port F */ -static struct resource ep93xx_f_gpio_resources[] = { - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x30, 0x04, "data"), - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x34, 0x04, "dir"), - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x4c, 0x1c, "intr"), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO0MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO1MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO2MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO3MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO4MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO5MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO6MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO7MUX), -}; - -static struct platform_device ep93xx_f_gpio = { - .name = "gpio-ep93xx", - .id = 5, - .num_resources = ARRAY_SIZE(ep93xx_f_gpio_resources), - .resource = ep93xx_f_gpio_resources, -}; - -/* port G */ -static struct resource ep93xx_g_gpio_resources[] = { - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x38, 0x04, "data"), - DEFINE_RES_MEM_NAMED(EP93XX_GPIO_PHYS_BASE + 0x3c, 0x04, "dir"), -}; - -static struct platform_device ep93xx_g_gpio = { - .name = "gpio-ep93xx", - .id = 6, - .num_resources = ARRAY_SIZE(ep93xx_g_gpio_resources), - .resource = ep93xx_g_gpio_resources, -}; - -static struct platform_device *ep93xx_gpio_device[] __initdata = { - &ep93xx_a_gpio, - &ep93xx_b_gpio, - &ep93xx_c_gpio, - &ep93xx_d_gpio, - &ep93xx_e_gpio, - &ep93xx_f_gpio, - &ep93xx_g_gpio, -}; - -/************************************************************************* - * EP93xx peripheral handling - *************************************************************************/ -#define EP93XX_UART_MCR_OFFSET (0x0100) - -static void ep93xx_uart_set_mctrl(struct amba_device *dev, - void __iomem *base, unsigned int mctrl) -{ - unsigned int mcr; - - mcr = 0; - if (mctrl & TIOCM_RTS) - mcr |= 2; - if (mctrl & TIOCM_DTR) - mcr |= 1; - - __raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET); -} - -static struct amba_pl010_data ep93xx_uart_data = { - .set_mctrl = ep93xx_uart_set_mctrl, -}; - -static AMBA_APB_DEVICE(uart1, "apb:uart1", 0x00041010, EP93XX_UART1_PHYS_BASE, - { IRQ_EP93XX_UART1 }, &ep93xx_uart_data); - -static AMBA_APB_DEVICE(uart2, "apb:uart2", 0x00041010, EP93XX_UART2_PHYS_BASE, - { IRQ_EP93XX_UART2 }, NULL); - -static AMBA_APB_DEVICE(uart3, "apb:uart3", 0x00041010, EP93XX_UART3_PHYS_BASE, - { IRQ_EP93XX_UART3 }, &ep93xx_uart_data); - -static struct resource ep93xx_rtc_resource[] = { - DEFINE_RES_MEM(EP93XX_RTC_PHYS_BASE, 0x10c), -}; - -static struct platform_device ep93xx_rtc_device = { - .name = "ep93xx-rtc", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_rtc_resource), - .resource = ep93xx_rtc_resource, -}; - -/************************************************************************* - * EP93xx OHCI USB Host - *************************************************************************/ - -static struct clk *ep93xx_ohci_host_clock; - -static int ep93xx_ohci_power_on(struct platform_device *pdev) -{ - if (!ep93xx_ohci_host_clock) { - ep93xx_ohci_host_clock = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(ep93xx_ohci_host_clock)) - return PTR_ERR(ep93xx_ohci_host_clock); - } - - return clk_prepare_enable(ep93xx_ohci_host_clock); -} - -static void ep93xx_ohci_power_off(struct platform_device *pdev) -{ - clk_disable(ep93xx_ohci_host_clock); -} - -static struct usb_ohci_pdata ep93xx_ohci_pdata = { - .power_on = ep93xx_ohci_power_on, - .power_off = ep93xx_ohci_power_off, - .power_suspend = ep93xx_ohci_power_off, -}; - -static struct resource ep93xx_ohci_resources[] = { - DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000), - DEFINE_RES_IRQ(IRQ_EP93XX_USB), -}; - -static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device ep93xx_ohci_device = { - .name = "ohci-platform", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), - .resource = ep93xx_ohci_resources, - .dev = { - .dma_mask = &ep93xx_ohci_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &ep93xx_ohci_pdata, - }, -}; - -/************************************************************************* - * EP93xx physmap'ed flash - *************************************************************************/ -static struct physmap_flash_data ep93xx_flash_data; - -static struct resource ep93xx_flash_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device ep93xx_flash = { - .name = "physmap-flash", - .id = 0, - .dev = { - .platform_data = &ep93xx_flash_data, - }, - .num_resources = 1, - .resource = &ep93xx_flash_resource, -}; - -/** - * ep93xx_register_flash() - Register the external flash device. - * @width: bank width in octets - * @start: resource start address - * @size: resource size - */ -void __init ep93xx_register_flash(unsigned int width, - resource_size_t start, resource_size_t size) -{ - ep93xx_flash_data.width = width; - - ep93xx_flash_resource.start = start; - ep93xx_flash_resource.end = start + size - 1; - - platform_device_register(&ep93xx_flash); -} - - -/************************************************************************* - * EP93xx ethernet peripheral handling - *************************************************************************/ -static struct ep93xx_eth_data ep93xx_eth_data; - -static struct resource ep93xx_eth_resource[] = { - DEFINE_RES_MEM(EP93XX_ETHERNET_PHYS_BASE, 0x10000), - DEFINE_RES_IRQ(IRQ_EP93XX_ETHERNET), -}; - -static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device ep93xx_eth_device = { - .name = "ep93xx-eth", - .id = -1, - .dev = { - .platform_data = &ep93xx_eth_data, - .coherent_dma_mask = DMA_BIT_MASK(32), - .dma_mask = &ep93xx_eth_dma_mask, - }, - .num_resources = ARRAY_SIZE(ep93xx_eth_resource), - .resource = ep93xx_eth_resource, -}; - -/** - * ep93xx_register_eth - Register the built-in ethernet platform device. - * @data: platform specific ethernet configuration (__initdata) - * @copy_addr: flag indicating that the MAC address should be copied - * from the IndAd registers (as programmed by the bootloader) - */ -void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) -{ - if (copy_addr) - memcpy_fromio(data->dev_addr, EP93XX_ETHERNET_BASE + 0x50, 6); - - ep93xx_eth_data = *data; - platform_device_register(&ep93xx_eth_device); -} - - -/************************************************************************* - * EP93xx i2c peripheral handling - *************************************************************************/ - -/* All EP93xx devices use the same two GPIO pins for I2C bit-banging */ -static struct gpiod_lookup_table ep93xx_i2c_gpiod_table = { - .dev_id = "i2c-gpio.0", - .table = { - /* Use local offsets on gpiochip/port "G" */ - GPIO_LOOKUP_IDX("gpio-ep93xx.6", 1, NULL, 0, - GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), - GPIO_LOOKUP_IDX("gpio-ep93xx.6", 0, NULL, 1, - GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), - { } - }, -}; - -static struct platform_device ep93xx_i2c_device = { - .name = "i2c-gpio", - .id = 0, - .dev = { - .platform_data = NULL, - }, -}; - -/** - * ep93xx_register_i2c - Register the i2c platform device. - * @devices: platform specific i2c bus device information (__initdata) - * @num: the number of devices on the i2c bus - */ -void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num) -{ - /* - * FIXME: this just sets the two pins as non-opendrain, as no - * platforms tries to do that anyway. Flag the applicable lines - * as open drain in the GPIO_LOOKUP above and the driver or - * gpiolib will handle open drain/open drain emulation as need - * be. Right now i2c-gpio emulates open drain which is not - * optimal. - */ - __raw_writel((0 << 1) | (0 << 0), - EP93XX_GPIO_EEDRIVE); - - i2c_register_board_info(0, devices, num); - gpiod_add_lookup_table(&ep93xx_i2c_gpiod_table); - platform_device_register(&ep93xx_i2c_device); -} - -/************************************************************************* - * EP93xx SPI peripheral handling - *************************************************************************/ -static struct ep93xx_spi_info ep93xx_spi_master_data; - -static struct resource ep93xx_spi_resources[] = { - DEFINE_RES_MEM(EP93XX_SPI_PHYS_BASE, 0x18), - DEFINE_RES_IRQ(IRQ_EP93XX_SSP), -}; - -static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device ep93xx_spi_device = { - .name = "ep93xx-spi", - .id = 0, - .dev = { - .platform_data = &ep93xx_spi_master_data, - .coherent_dma_mask = DMA_BIT_MASK(32), - .dma_mask = &ep93xx_spi_dma_mask, - }, - .num_resources = ARRAY_SIZE(ep93xx_spi_resources), - .resource = ep93xx_spi_resources, -}; - -/** - * ep93xx_register_spi() - registers spi platform device - * @info: ep93xx board specific spi master info (__initdata) - * @devices: SPI devices to register (__initdata) - * @num: number of SPI devices to register - * - * This function registers platform device for the EP93xx SPI controller and - * also makes sure that SPI pins are muxed so that I2S is not using those pins. - */ -void __init ep93xx_register_spi(struct ep93xx_spi_info *info, - struct spi_board_info *devices, int num) -{ - /* - * When SPI is used, we need to make sure that I2S is muxed off from - * SPI pins. - */ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONSSP); - - ep93xx_spi_master_data = *info; - spi_register_board_info(devices, num); - platform_device_register(&ep93xx_spi_device); -} - -/************************************************************************* - * EP93xx LEDs - *************************************************************************/ -static const struct gpio_led ep93xx_led_pins[] __initconst = { - { - .name = "platform:grled", - }, { - .name = "platform:rdled", - }, -}; - -static const struct gpio_led_platform_data ep93xx_led_data __initconst = { - .num_leds = ARRAY_SIZE(ep93xx_led_pins), - .leds = ep93xx_led_pins, -}; - -static struct gpiod_lookup_table ep93xx_leds_gpio_table = { - .dev_id = "leds-gpio", - .table = { - /* Use local offsets on gpiochip/port "E" */ - GPIO_LOOKUP_IDX("gpio-ep93xx.4", 0, NULL, 0, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("gpio-ep93xx.4", 1, NULL, 1, GPIO_ACTIVE_HIGH), - { } - }, -}; - -/************************************************************************* - * EP93xx pwm peripheral handling - *************************************************************************/ -static struct resource ep93xx_pwm0_resource[] = { - DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE, 0x10), -}; - -static struct platform_device ep93xx_pwm0_device = { - .name = "ep93xx-pwm", - .id = 0, - .num_resources = ARRAY_SIZE(ep93xx_pwm0_resource), - .resource = ep93xx_pwm0_resource, -}; - -static struct resource ep93xx_pwm1_resource[] = { - DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE + 0x20, 0x10), -}; - -static struct platform_device ep93xx_pwm1_device = { - .name = "ep93xx-pwm", - .id = 1, - .num_resources = ARRAY_SIZE(ep93xx_pwm1_resource), - .resource = ep93xx_pwm1_resource, -}; - -void __init ep93xx_register_pwm(int pwm0, int pwm1) -{ - if (pwm0) - platform_device_register(&ep93xx_pwm0_device); - - /* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */ - if (pwm1) - platform_device_register(&ep93xx_pwm1_device); -} - -/************************************************************************* - * EP93xx video peripheral handling - *************************************************************************/ -static struct ep93xxfb_mach_info ep93xxfb_data; - -static struct resource ep93xx_fb_resource[] = { - DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE, 0x800), -}; - -static struct platform_device ep93xx_fb_device = { - .name = "ep93xx-fb", - .id = -1, - .dev = { - .platform_data = &ep93xxfb_data, - .coherent_dma_mask = DMA_BIT_MASK(32), - .dma_mask = &ep93xx_fb_device.dev.coherent_dma_mask, - }, - .num_resources = ARRAY_SIZE(ep93xx_fb_resource), - .resource = ep93xx_fb_resource, -}; - -/* The backlight use a single register in the framebuffer's register space */ -#define EP93XX_RASTER_REG_BRIGHTNESS 0x20 - -static struct resource ep93xx_bl_resources[] = { - DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE + - EP93XX_RASTER_REG_BRIGHTNESS, 0x04), -}; - -static struct platform_device ep93xx_bl_device = { - .name = "ep93xx-bl", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_bl_resources), - .resource = ep93xx_bl_resources, -}; - -/** - * ep93xx_register_fb - Register the framebuffer platform device. - * @data: platform specific framebuffer configuration (__initdata) - */ -void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data) -{ - ep93xxfb_data = *data; - platform_device_register(&ep93xx_fb_device); - platform_device_register(&ep93xx_bl_device); -} - - -/************************************************************************* - * EP93xx matrix keypad peripheral handling - *************************************************************************/ -static struct ep93xx_keypad_platform_data ep93xx_keypad_data; - -static struct resource ep93xx_keypad_resource[] = { - DEFINE_RES_MEM(EP93XX_KEY_MATRIX_PHYS_BASE, 0x0c), - DEFINE_RES_IRQ(IRQ_EP93XX_KEY), -}; - -static struct platform_device ep93xx_keypad_device = { - .name = "ep93xx-keypad", - .id = -1, - .dev = { - .platform_data = &ep93xx_keypad_data, - }, - .num_resources = ARRAY_SIZE(ep93xx_keypad_resource), - .resource = ep93xx_keypad_resource, -}; - -/** - * ep93xx_register_keypad - Register the keypad platform device. - * @data: platform specific keypad configuration (__initdata) - */ -void __init ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data) -{ - ep93xx_keypad_data = *data; - platform_device_register(&ep93xx_keypad_device); -} - -/************************************************************************* - * EP93xx I2S audio peripheral handling - *************************************************************************/ -static struct resource ep93xx_i2s_resource[] = { - DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100), - DEFINE_RES_IRQ(IRQ_EP93XX_SAI), -}; - -static struct platform_device ep93xx_i2s_device = { - .name = "ep93xx-i2s", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_i2s_resource), - .resource = ep93xx_i2s_resource, -}; - -static struct platform_device ep93xx_pcm_device = { - .name = "ep93xx-pcm-audio", - .id = -1, -}; - -void __init ep93xx_register_i2s(void) -{ - platform_device_register(&ep93xx_i2s_device); - platform_device_register(&ep93xx_pcm_device); -} - -#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ - EP93XX_SYSCON_DEVCFG_I2SONAC97) - -#define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \ - EP93XX_SYSCON_I2SCLKDIV_SPOL) - -int ep93xx_i2s_acquire(void) -{ - unsigned val; - - ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_I2SONAC97, - EP93XX_SYSCON_DEVCFG_I2S_MASK); - - /* - * This is potentially racy with the clock api for i2s_mclk, sclk and - * lrclk. Since the i2s driver is the only user of those clocks we - * rely on it to prevent parallel use of this function and the - * clock api for the i2s clocks. - */ - val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV); - val &= ~EP93XX_I2SCLKDIV_MASK; - val |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL; - ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV); - - return 0; -} -EXPORT_SYMBOL(ep93xx_i2s_acquire); - -void ep93xx_i2s_release(void) -{ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK); -} -EXPORT_SYMBOL(ep93xx_i2s_release); - -/************************************************************************* - * EP93xx AC97 audio peripheral handling - *************************************************************************/ -static struct resource ep93xx_ac97_resources[] = { - DEFINE_RES_MEM(EP93XX_AAC_PHYS_BASE, 0xac), - DEFINE_RES_IRQ(IRQ_EP93XX_AACINTR), -}; - -static struct platform_device ep93xx_ac97_device = { - .name = "ep93xx-ac97", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_ac97_resources), - .resource = ep93xx_ac97_resources, -}; - -void __init ep93xx_register_ac97(void) -{ - /* - * Make sure that the AC97 pins are not used by I2S. - */ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97); - - platform_device_register(&ep93xx_ac97_device); - platform_device_register(&ep93xx_pcm_device); -} - -/************************************************************************* - * EP93xx Watchdog - *************************************************************************/ -static struct resource ep93xx_wdt_resources[] = { - DEFINE_RES_MEM(EP93XX_WATCHDOG_PHYS_BASE, 0x08), -}; - -static struct platform_device ep93xx_wdt_device = { - .name = "ep93xx-wdt", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_wdt_resources), - .resource = ep93xx_wdt_resources, -}; - -/************************************************************************* - * EP93xx IDE - *************************************************************************/ -static struct resource ep93xx_ide_resources[] = { - DEFINE_RES_MEM(EP93XX_IDE_PHYS_BASE, 0x38), - DEFINE_RES_IRQ(IRQ_EP93XX_EXT3), -}; - -static struct platform_device ep93xx_ide_device = { - .name = "ep93xx-ide", - .id = -1, - .dev = { - .dma_mask = &ep93xx_ide_device.dev.coherent_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(ep93xx_ide_resources), - .resource = ep93xx_ide_resources, -}; - -void __init ep93xx_register_ide(void) -{ - platform_device_register(&ep93xx_ide_device); -} - -/************************************************************************* - * EP93xx ADC - *************************************************************************/ -static struct resource ep93xx_adc_resources[] = { - DEFINE_RES_MEM(EP93XX_ADC_PHYS_BASE, 0x28), - DEFINE_RES_IRQ(IRQ_EP93XX_TOUCH), -}; - -static struct platform_device ep93xx_adc_device = { - .name = "ep93xx-adc", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_adc_resources), - .resource = ep93xx_adc_resources, -}; - -void __init ep93xx_register_adc(void) -{ - /* Power up ADC, deactivate Touch Screen Controller */ - ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_TIN, - EP93XX_SYSCON_DEVCFG_ADCPD); - - platform_device_register(&ep93xx_adc_device); -} - -/************************************************************************* - * EP93xx Security peripheral - *************************************************************************/ - -/* - * The Maverick Key is 256 bits of micro fuses blown at the factory during - * manufacturing to uniquely identify a part. - * - * See: http://arm.cirrus.com/forum/viewtopic.php?t=486&highlight=maverick+key - */ -#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x)) -#define EP93XX_SECURITY_SECFLG EP93XX_SECURITY_REG(0x2400) -#define EP93XX_SECURITY_FUSEFLG EP93XX_SECURITY_REG(0x2410) -#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440) -#define EP93XX_SECURITY_UNIQCHK EP93XX_SECURITY_REG(0x2450) -#define EP93XX_SECURITY_UNIQVAL EP93XX_SECURITY_REG(0x2460) -#define EP93XX_SECURITY_SECID1 EP93XX_SECURITY_REG(0x2500) -#define EP93XX_SECURITY_SECID2 EP93XX_SECURITY_REG(0x2504) -#define EP93XX_SECURITY_SECCHK1 EP93XX_SECURITY_REG(0x2520) -#define EP93XX_SECURITY_SECCHK2 EP93XX_SECURITY_REG(0x2524) -#define EP93XX_SECURITY_UNIQID2 EP93XX_SECURITY_REG(0x2700) -#define EP93XX_SECURITY_UNIQID3 EP93XX_SECURITY_REG(0x2704) -#define EP93XX_SECURITY_UNIQID4 EP93XX_SECURITY_REG(0x2708) -#define EP93XX_SECURITY_UNIQID5 EP93XX_SECURITY_REG(0x270c) - -static char ep93xx_soc_id[33]; - -static const char __init *ep93xx_get_soc_id(void) -{ - unsigned int id, id2, id3, id4, id5; - - if (__raw_readl(EP93XX_SECURITY_UNIQVAL) != 1) - return "bad Hamming code"; - - id = __raw_readl(EP93XX_SECURITY_UNIQID); - id2 = __raw_readl(EP93XX_SECURITY_UNIQID2); - id3 = __raw_readl(EP93XX_SECURITY_UNIQID3); - id4 = __raw_readl(EP93XX_SECURITY_UNIQID4); - id5 = __raw_readl(EP93XX_SECURITY_UNIQID5); - - if (id != id2) - return "invalid"; - - /* Toss the unique ID into the entropy pool */ - add_device_randomness(&id2, 4); - add_device_randomness(&id3, 4); - add_device_randomness(&id4, 4); - add_device_randomness(&id5, 4); - - snprintf(ep93xx_soc_id, sizeof(ep93xx_soc_id), - "%08x%08x%08x%08x", id2, id3, id4, id5); - - return ep93xx_soc_id; -} - -static const char __init *ep93xx_get_soc_rev(void) -{ - int rev = ep93xx_chip_revision(); - - switch (rev) { - case EP93XX_CHIP_REV_D0: - return "D0"; - case EP93XX_CHIP_REV_D1: - return "D1"; - case EP93XX_CHIP_REV_E0: - return "E0"; - case EP93XX_CHIP_REV_E1: - return "E1"; - case EP93XX_CHIP_REV_E2: - return "E2"; - default: - return "unknown"; - } -} - -static const char __init *ep93xx_get_machine_name(void) -{ - return kasprintf(GFP_KERNEL,"%s", machine_desc->name); -} - -static struct device __init *ep93xx_init_soc(void) -{ - struct soc_device_attribute *soc_dev_attr; - struct soc_device *soc_dev; - - soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); - if (!soc_dev_attr) - return NULL; - - soc_dev_attr->machine = ep93xx_get_machine_name(); - soc_dev_attr->family = "Cirrus Logic EP93xx"; - soc_dev_attr->revision = ep93xx_get_soc_rev(); - soc_dev_attr->soc_id = ep93xx_get_soc_id(); - - soc_dev = soc_device_register(soc_dev_attr); - if (IS_ERR(soc_dev)) { - kfree(soc_dev_attr->machine); - kfree(soc_dev_attr); - return NULL; - } - - return soc_device_to_device(soc_dev); -} - -struct device __init *ep93xx_init_devices(void) -{ - struct device *parent; - unsigned int i; - - /* Disallow access to MaverickCrunch initially */ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); - - /* Default all ports to GPIO */ - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | - EP93XX_SYSCON_DEVCFG_GONK | - EP93XX_SYSCON_DEVCFG_EONIDE | - EP93XX_SYSCON_DEVCFG_GONIDE | - EP93XX_SYSCON_DEVCFG_HONIDE); - - parent = ep93xx_init_soc(); - - /* Get the GPIO working early, other devices need it */ - for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_device); i++) - platform_device_register(ep93xx_gpio_device[i]); - - amba_device_register(&uart1_device, &iomem_resource); - amba_device_register(&uart2_device, &iomem_resource); - amba_device_register(&uart3_device, &iomem_resource); - - platform_device_register(&ep93xx_rtc_device); - platform_device_register(&ep93xx_ohci_device); - platform_device_register(&ep93xx_wdt_device); - - gpiod_add_lookup_table(&ep93xx_leds_gpio_table); - gpio_led_register_device(-1, &ep93xx_led_data); - - return parent; -} - -void ep93xx_restart(enum reboot_mode mode, const char *cmd) -{ - /* - * Set then clear the SWRST bit to initiate a software reset - */ - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST); - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST); - - while (1) - ; -} diff --git a/arch/arm/mach-ep93xx/dma.c b/arch/arm/mach-ep93xx/dma.c deleted file mode 100644 index 74515acab8ef..000000000000 --- a/arch/arm/mach-ep93xx/dma.c +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/dma.c - * - * Platform support code for the EP93xx dmaengine driver. - * - * Copyright (C) 2011 Mika Westerberg - * - * This work is based on the original dma-m2p implementation with - * following copyrights: - * - * Copyright (C) 2006 Lennert Buytenhek - * Copyright (C) 2006 Applied Data Systems - * Copyright (C) 2009 Ryan Mallon - */ - -#include -#include -#include -#include -#include -#include - -#include -#include "hardware.h" - -#include "soc.h" - -#define DMA_CHANNEL(_name, _base, _irq) \ - { .name = (_name), .base = (_base), .irq = (_irq) } - -/* - * DMA M2P channels. - * - * On the EP93xx chip the following peripherals my be allocated to the 10 - * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive). - * - * I2S contains 3 Tx and 3 Rx DMA Channels - * AAC contains 3 Tx and 3 Rx DMA Channels - * UART1 contains 1 Tx and 1 Rx DMA Channels - * UART2 contains 1 Tx and 1 Rx DMA Channels - * UART3 contains 1 Tx and 1 Rx DMA Channels - * IrDA contains 1 Tx and 1 Rx DMA Channels - * - * Registers are mapped statically in ep93xx_map_io(). - */ -static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = { - DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0), - DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1), - DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2), - DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3), - DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4), - DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5), - DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6), - DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7), - DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8), - DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9), -}; - -static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = { - .channels = ep93xx_dma_m2p_channels, - .num_channels = ARRAY_SIZE(ep93xx_dma_m2p_channels), -}; - -static u64 ep93xx_dma_m2p_mask = DMA_BIT_MASK(32); - -static struct platform_device ep93xx_dma_m2p_device = { - .name = "ep93xx-dma-m2p", - .id = -1, - .dev = { - .platform_data = &ep93xx_dma_m2p_data, - .dma_mask = &ep93xx_dma_m2p_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -/* - * DMA M2M channels. - * - * There are 2 M2M channels which support memcpy/memset and in addition simple - * hardware requests from/to SSP and IDE. We do not implement an external - * hardware requests. - * - * Registers are mapped statically in ep93xx_map_io(). - */ -static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = { - DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0), - DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1), -}; - -static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = { - .channels = ep93xx_dma_m2m_channels, - .num_channels = ARRAY_SIZE(ep93xx_dma_m2m_channels), -}; - -static u64 ep93xx_dma_m2m_mask = DMA_BIT_MASK(32); - -static struct platform_device ep93xx_dma_m2m_device = { - .name = "ep93xx-dma-m2m", - .id = -1, - .dev = { - .platform_data = &ep93xx_dma_m2m_data, - .dma_mask = &ep93xx_dma_m2m_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -static int __init ep93xx_dma_init(void) -{ - platform_device_register(&ep93xx_dma_m2p_device); - platform_device_register(&ep93xx_dma_m2m_device); - return 0; -} -arch_initcall(ep93xx_dma_init); diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c deleted file mode 100644 index 356b0460c7ed..000000000000 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ /dev/null @@ -1,368 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/edb93xx.c - * Cirrus Logic EDB93xx Development Board support. - * - * EDB93XX, EDB9301, EDB9307A - * Copyright (C) 2008-2009 H Hartley Sweeten - * - * EDB9302 - * Copyright (C) 2006 George Kashperko - * - * EDB9302A, EDB9315, EDB9315A - * Copyright (C) 2006 Lennert Buytenhek - * - * EDB9307 - * Copyright (C) 2007 Herbert Valerio Riedel - * - * EDB9312 - * Copyright (C) 2006 Infosys Technologies Limited - * Toufeeq Hussain - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "hardware.h" -#include -#include -#include "gpio-ep93xx.h" - -#include -#include - -#include "soc.h" - -static void __init edb93xx_register_flash(void) -{ - if (machine_is_edb9307() || machine_is_edb9312() || - machine_is_edb9315()) { - ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M); - } else { - ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M); - } -} - -static struct ep93xx_eth_data __initdata edb93xx_eth_data = { - .phy_id = 1, -}; - - -/************************************************************************* - * EDB93xx i2c peripheral handling - *************************************************************************/ - -static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = { - { - I2C_BOARD_INFO("isl1208", 0x6f), - }, -}; - -static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = { - { - I2C_BOARD_INFO("ds1337", 0x68), - }, -}; - -static void __init edb93xx_register_i2c(void) -{ - if (machine_is_edb9302a() || machine_is_edb9307a() || - machine_is_edb9315a()) { - ep93xx_register_i2c(edb93xxa_i2c_board_info, - ARRAY_SIZE(edb93xxa_i2c_board_info)); - } else if (machine_is_edb9302() || machine_is_edb9307() - || machine_is_edb9312() || machine_is_edb9315()) { - ep93xx_register_i2c(edb93xx_i2c_board_info, - ARRAY_SIZE(edb93xx_i2c_board_info)); - } -} - - -/************************************************************************* - * EDB93xx SPI peripheral handling - *************************************************************************/ -static struct cs4271_platform_data edb93xx_cs4271_data = { - /* Intentionally left blank */ -}; - -static struct spi_board_info edb93xx_spi_board_info[] __initdata = { - { - .modalias = "cs4271", - .platform_data = &edb93xx_cs4271_data, - .max_speed_hz = 6000000, - .bus_num = 0, - .chip_select = 0, - .mode = SPI_MODE_3, - }, -}; - -static struct gpiod_lookup_table edb93xx_spi_cs_gpio_table = { - .dev_id = "spi0", - .table = { - GPIO_LOOKUP("gpio-ep93xx.0", 6, "cs", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct ep93xx_spi_info edb93xx_spi_info __initdata = { - /* Intentionally left blank */ -}; - -static struct gpiod_lookup_table edb93xx_cs4272_edb9301_gpio_table = { - .dev_id = "spi0.0", /* CS0 on SPI0 */ - .table = { - GPIO_LOOKUP("A", 1, "reset", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct gpiod_lookup_table edb93xx_cs4272_edb9302_gpio_table = { - .dev_id = "spi0.0", /* CS0 on SPI0 */ - .table = { - GPIO_LOOKUP("H", 2, "reset", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct gpiod_lookup_table edb93xx_cs4272_edb9315_gpio_table = { - .dev_id = "spi0.0", /* CS0 on SPI0 */ - .table = { - GPIO_LOOKUP("B", 6, "reset", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static void __init edb93xx_register_spi(void) -{ - if (machine_is_edb9301() || machine_is_edb9302()) - gpiod_add_lookup_table(&edb93xx_cs4272_edb9301_gpio_table); - else if (machine_is_edb9302a() || machine_is_edb9307a()) - gpiod_add_lookup_table(&edb93xx_cs4272_edb9302_gpio_table); - else if (machine_is_edb9315a()) - gpiod_add_lookup_table(&edb93xx_cs4272_edb9315_gpio_table); - - gpiod_add_lookup_table(&edb93xx_spi_cs_gpio_table); - ep93xx_register_spi(&edb93xx_spi_info, edb93xx_spi_board_info, - ARRAY_SIZE(edb93xx_spi_board_info)); -} - - -/************************************************************************* - * EDB93xx I2S - *************************************************************************/ -static struct platform_device edb93xx_audio_device = { - .name = "edb93xx-audio", - .id = -1, -}; - -static int __init edb93xx_has_audio(void) -{ - return (machine_is_edb9301() || machine_is_edb9302() || - machine_is_edb9302a() || machine_is_edb9307a() || - machine_is_edb9315a()); -} - -static void __init edb93xx_register_i2s(void) -{ - if (edb93xx_has_audio()) { - ep93xx_register_i2s(); - platform_device_register(&edb93xx_audio_device); - } -} - - -/************************************************************************* - * EDB93xx pwm - *************************************************************************/ -static void __init edb93xx_register_pwm(void) -{ - if (machine_is_edb9301() || - machine_is_edb9302() || machine_is_edb9302a()) { - /* EP9301 and EP9302 only have pwm.1 (EGPIO14) */ - ep93xx_register_pwm(0, 1); - } else if (machine_is_edb9307() || machine_is_edb9307a()) { - /* EP9307 only has pwm.0 (PWMOUT) */ - ep93xx_register_pwm(1, 0); - } else { - /* EP9312 and EP9315 have both */ - ep93xx_register_pwm(1, 1); - } -} - - -/************************************************************************* - * EDB93xx framebuffer - *************************************************************************/ -static struct ep93xxfb_mach_info __initdata edb93xxfb_info = { - .flags = 0, -}; - -static int __init edb93xx_has_fb(void) -{ - /* These platforms have an ep93xx with video capability */ - return machine_is_edb9307() || machine_is_edb9307a() || - machine_is_edb9312() || machine_is_edb9315() || - machine_is_edb9315a(); -} - -static void __init edb93xx_register_fb(void) -{ - if (!edb93xx_has_fb()) - return; - - if (machine_is_edb9307a() || machine_is_edb9315a()) - edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN0; - else - edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN3; - - ep93xx_register_fb(&edb93xxfb_info); -} - - -/************************************************************************* - * EDB93xx IDE - *************************************************************************/ -static int __init edb93xx_has_ide(void) -{ - /* - * Although EDB9312 and EDB9315 do have IDE capability, they have - * INTRQ line wired as pull-up, which makes using IDE interface - * problematic. - */ - return machine_is_edb9312() || machine_is_edb9315() || - machine_is_edb9315a(); -} - -static void __init edb93xx_register_ide(void) -{ - if (!edb93xx_has_ide()) - return; - - ep93xx_register_ide(); -} - - -static void __init edb93xx_init_machine(void) -{ - ep93xx_init_devices(); - edb93xx_register_flash(); - ep93xx_register_eth(&edb93xx_eth_data, 1); - edb93xx_register_i2c(); - edb93xx_register_spi(); - edb93xx_register_i2s(); - edb93xx_register_pwm(); - edb93xx_register_fb(); - edb93xx_register_ide(); - ep93xx_register_adc(); -} - - -#ifdef CONFIG_MACH_EDB9301 -MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board") - /* Maintainer: H Hartley Sweeten */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9302 -MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board") - /* Maintainer: George Kashperko */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9302A -MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board") - /* Maintainer: Lennert Buytenhek */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9307 -MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board") - /* Maintainer: Herbert Valerio Riedel */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9307A -MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board") - /* Maintainer: H Hartley Sweeten */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9312 -MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board") - /* Maintainer: Toufeeq Hussain */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9315 -MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board") - /* Maintainer: Lennert Buytenhek */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9315A -MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board") - /* Maintainer: Lennert Buytenhek */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif diff --git a/arch/arm/mach-ep93xx/ep93xx-regs.h b/arch/arm/mach-ep93xx/ep93xx-regs.h deleted file mode 100644 index 8fa3646de0a4..000000000000 --- a/arch/arm/mach-ep93xx/ep93xx-regs.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_ARCH_EP93XX_REGS_H -#define __ASM_ARCH_EP93XX_REGS_H - -/* - * EP93xx linux memory map: - * - * virt phys size - * fe800000 5M per-platform mappings - * fed00000 80800000 2M APB - * fef00000 80000000 1M AHB - */ - -#define EP93XX_AHB_PHYS_BASE 0x80000000 -#define EP93XX_AHB_VIRT_BASE 0xfef00000 -#define EP93XX_AHB_SIZE 0x00100000 - -#define EP93XX_AHB_PHYS(x) (EP93XX_AHB_PHYS_BASE + (x)) -#define EP93XX_AHB_IOMEM(x) IOMEM(EP93XX_AHB_VIRT_BASE + (x)) - -#define EP93XX_APB_PHYS_BASE 0x80800000 -#define EP93XX_APB_VIRT_BASE 0xfed00000 -#define EP93XX_APB_SIZE 0x00200000 - -#define EP93XX_APB_PHYS(x) (EP93XX_APB_PHYS_BASE + (x)) -#define EP93XX_APB_IOMEM(x) IOMEM(EP93XX_APB_VIRT_BASE + (x)) - -/* APB UARTs */ -#define EP93XX_UART1_PHYS_BASE EP93XX_APB_PHYS(0x000c0000) -#define EP93XX_UART1_BASE EP93XX_APB_IOMEM(0x000c0000) - -#define EP93XX_UART2_PHYS_BASE EP93XX_APB_PHYS(0x000d0000) -#define EP93XX_UART2_BASE EP93XX_APB_IOMEM(0x000d0000) - -#define EP93XX_UART3_PHYS_BASE EP93XX_APB_PHYS(0x000e0000) -#define EP93XX_UART3_BASE EP93XX_APB_IOMEM(0x000e0000) - -#endif diff --git a/arch/arm/mach-ep93xx/gpio-ep93xx.h b/arch/arm/mach-ep93xx/gpio-ep93xx.h deleted file mode 100644 index 7b46eb7e5507..000000000000 --- a/arch/arm/mach-ep93xx/gpio-ep93xx.h +++ /dev/null @@ -1,111 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Include file for the EP93XX GPIO controller machine specifics */ - -#ifndef __GPIO_EP93XX_H -#define __GPIO_EP93XX_H - -#include "ep93xx-regs.h" - -#define EP93XX_GPIO_PHYS_BASE EP93XX_APB_PHYS(0x00040000) -#define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000) -#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) -#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c) -#define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0) -#define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc) -#define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8) - -/* GPIO port A. */ -#define EP93XX_GPIO_LINE_A(x) ((x) + 0) -#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0) -#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1) -#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2) -#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3) -#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4) -#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5) -#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6) -#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7) - -/* GPIO port B. */ -#define EP93XX_GPIO_LINE_B(x) ((x) + 8) -#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0) -#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1) -#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2) -#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3) -#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4) -#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5) -#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6) -#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7) - -/* GPIO port C. */ -#define EP93XX_GPIO_LINE_C(x) ((x) + 40) -#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0) -#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1) -#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2) -#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3) -#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4) -#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5) -#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6) -#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7) - -/* GPIO port D. */ -#define EP93XX_GPIO_LINE_D(x) ((x) + 24) -#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0) -#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1) -#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2) -#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3) -#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4) -#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5) -#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6) -#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7) - -/* GPIO port E. */ -#define EP93XX_GPIO_LINE_E(x) ((x) + 32) -#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0) -#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1) -#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2) -#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3) -#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4) -#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5) -#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6) -#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7) - -/* GPIO port F. */ -#define EP93XX_GPIO_LINE_F(x) ((x) + 16) -#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0) -#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1) -#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2) -#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3) -#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4) -#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5) -#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6) -#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7) - -/* GPIO port G. */ -#define EP93XX_GPIO_LINE_G(x) ((x) + 48) -#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0) -#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1) -#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2) -#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3) -#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4) -#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5) -#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6) -#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7) - -/* GPIO port H. */ -#define EP93XX_GPIO_LINE_H(x) ((x) + 56) -#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0) -#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1) -#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2) -#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3) -#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4) -#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5) -#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6) -#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7) - -/* maximum value for gpio line identifiers */ -#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7) - -/* maximum value for irq capable line identifiers */ -#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7) - -#endif /* __GPIO_EP93XX_H */ diff --git a/arch/arm/mach-ep93xx/hardware.h b/arch/arm/mach-ep93xx/hardware.h deleted file mode 100644 index e7d850e04782..000000000000 --- a/arch/arm/mach-ep93xx/hardware.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * arch/arm/mach-ep93xx/include/mach/hardware.h - */ - -#ifndef __ASM_ARCH_HARDWARE_H -#define __ASM_ARCH_HARDWARE_H - -#include "platform.h" - -/* - * The EP93xx has two external crystal oscillators. To generate the - * required high-frequency clocks, the processor uses two phase-locked- - * loops (PLLs) to multiply the incoming external clock signal to much - * higher frequencies that are then divided down by programmable dividers - * to produce the needed clocks. The PLLs operate independently of one - * another. - */ -#define EP93XX_EXT_CLK_RATE 14745600 -#define EP93XX_EXT_RTC_RATE 32768 - -#define EP93XX_KEYTCHCLK_DIV4 (EP93XX_EXT_CLK_RATE / 4) -#define EP93XX_KEYTCHCLK_DIV16 (EP93XX_EXT_CLK_RATE / 16) - -#endif diff --git a/arch/arm/mach-ep93xx/irqs.h b/arch/arm/mach-ep93xx/irqs.h deleted file mode 100644 index 353201b90c66..000000000000 --- a/arch/arm/mach-ep93xx/irqs.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_ARCH_IRQS_H -#define __ASM_ARCH_IRQS_H - -#define IRQ_EP93XX_VIC0 1 - -#define IRQ_EP93XX_COMMRX (IRQ_EP93XX_VIC0 + 2) -#define IRQ_EP93XX_COMMTX (IRQ_EP93XX_VIC0 + 3) -#define IRQ_EP93XX_TIMER1 (IRQ_EP93XX_VIC0 + 4) -#define IRQ_EP93XX_TIMER2 (IRQ_EP93XX_VIC0 + 5) -#define IRQ_EP93XX_AACINTR (IRQ_EP93XX_VIC0 + 6) -#define IRQ_EP93XX_DMAM2P0 (IRQ_EP93XX_VIC0 + 7) -#define IRQ_EP93XX_DMAM2P1 (IRQ_EP93XX_VIC0 + 8) -#define IRQ_EP93XX_DMAM2P2 (IRQ_EP93XX_VIC0 + 9) -#define IRQ_EP93XX_DMAM2P3 (IRQ_EP93XX_VIC0 + 10) -#define IRQ_EP93XX_DMAM2P4 (IRQ_EP93XX_VIC0 + 11) -#define IRQ_EP93XX_DMAM2P5 (IRQ_EP93XX_VIC0 + 12) -#define IRQ_EP93XX_DMAM2P6 (IRQ_EP93XX_VIC0 + 13) -#define IRQ_EP93XX_DMAM2P7 (IRQ_EP93XX_VIC0 + 14) -#define IRQ_EP93XX_DMAM2P8 (IRQ_EP93XX_VIC0 + 15) -#define IRQ_EP93XX_DMAM2P9 (IRQ_EP93XX_VIC0 + 16) -#define IRQ_EP93XX_DMAM2M0 (IRQ_EP93XX_VIC0 + 17) -#define IRQ_EP93XX_DMAM2M1 (IRQ_EP93XX_VIC0 + 18) -#define IRQ_EP93XX_GPIO0MUX (IRQ_EP93XX_VIC0 + 19) -#define IRQ_EP93XX_GPIO1MUX (IRQ_EP93XX_VIC0 + 20) -#define IRQ_EP93XX_GPIO2MUX (IRQ_EP93XX_VIC0 + 21) -#define IRQ_EP93XX_GPIO3MUX (IRQ_EP93XX_VIC0 + 22) -#define IRQ_EP93XX_UART1RX (IRQ_EP93XX_VIC0 + 23) -#define IRQ_EP93XX_UART1TX (IRQ_EP93XX_VIC0 + 24) -#define IRQ_EP93XX_UART2RX (IRQ_EP93XX_VIC0 + 25) -#define IRQ_EP93XX_UART2TX (IRQ_EP93XX_VIC0 + 26) -#define IRQ_EP93XX_UART3RX (IRQ_EP93XX_VIC0 + 27) -#define IRQ_EP93XX_UART3TX (IRQ_EP93XX_VIC0 + 28) -#define IRQ_EP93XX_KEY (IRQ_EP93XX_VIC0 + 29) -#define IRQ_EP93XX_TOUCH (IRQ_EP93XX_VIC0 + 30) -#define EP93XX_VIC1_VALID_IRQ_MASK 0x7ffffffc - -#define IRQ_EP93XX_VIC1 (IRQ_EP93XX_VIC0 + 32) - -#define IRQ_EP93XX_EXT0 (IRQ_EP93XX_VIC1 + 0) -#define IRQ_EP93XX_EXT1 (IRQ_EP93XX_VIC1 + 1) -#define IRQ_EP93XX_EXT2 (IRQ_EP93XX_VIC1 + 2) -#define IRQ_EP93XX_64HZ (IRQ_EP93XX_VIC1 + 3) -#define IRQ_EP93XX_WATCHDOG (IRQ_EP93XX_VIC1 + 4) -#define IRQ_EP93XX_RTC (IRQ_EP93XX_VIC1 + 5) -#define IRQ_EP93XX_IRDA (IRQ_EP93XX_VIC1 + 6) -#define IRQ_EP93XX_ETHERNET (IRQ_EP93XX_VIC1 + 7) -#define IRQ_EP93XX_EXT3 (IRQ_EP93XX_VIC1 + 8) -#define IRQ_EP93XX_PROG (IRQ_EP93XX_VIC1 + 9) -#define IRQ_EP93XX_1HZ (IRQ_EP93XX_VIC1 + 10) -#define IRQ_EP93XX_VSYNC (IRQ_EP93XX_VIC1 + 11) -#define IRQ_EP93XX_VIDEO_FIFO (IRQ_EP93XX_VIC1 + 12) -#define IRQ_EP93XX_SSP1RX (IRQ_EP93XX_VIC1 + 13) -#define IRQ_EP93XX_SSP1TX (IRQ_EP93XX_VIC1 + 14) -#define IRQ_EP93XX_GPIO4MUX (IRQ_EP93XX_VIC1 + 15) -#define IRQ_EP93XX_GPIO5MUX (IRQ_EP93XX_VIC1 + 16) -#define IRQ_EP93XX_GPIO6MUX (IRQ_EP93XX_VIC1 + 17) -#define IRQ_EP93XX_GPIO7MUX (IRQ_EP93XX_VIC1 + 18) -#define IRQ_EP93XX_TIMER3 (IRQ_EP93XX_VIC1 + 19) -#define IRQ_EP93XX_UART1 (IRQ_EP93XX_VIC1 + 20) -#define IRQ_EP93XX_SSP (IRQ_EP93XX_VIC1 + 21) -#define IRQ_EP93XX_UART2 (IRQ_EP93XX_VIC1 + 22) -#define IRQ_EP93XX_UART3 (IRQ_EP93XX_VIC1 + 23) -#define IRQ_EP93XX_USB (IRQ_EP93XX_VIC1 + 24) -#define IRQ_EP93XX_ETHERNET_PME (IRQ_EP93XX_VIC1 + 25) -#define IRQ_EP93XX_DSP (IRQ_EP93XX_VIC1 + 26) -#define IRQ_EP93XX_GPIO_AB (IRQ_EP93XX_VIC1 + 27) -#define IRQ_EP93XX_SAI (IRQ_EP93XX_VIC1 + 28) -#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff - -#define NR_EP93XX_IRQS (IRQ_EP93XX_VIC1 + 32 + 24) - -#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x)) -#define EP93XX_BOARD_IRQS 32 - -#endif diff --git a/arch/arm/mach-ep93xx/platform.h b/arch/arm/mach-ep93xx/platform.h deleted file mode 100644 index 5fb1b919133f..000000000000 --- a/arch/arm/mach-ep93xx/platform.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * arch/arm/mach-ep93xx/include/mach/platform.h - */ - -#ifndef __ASSEMBLY__ - -#include -#include - -struct device; -struct i2c_board_info; -struct spi_board_info; -struct platform_device; -struct ep93xxfb_mach_info; -struct ep93xx_keypad_platform_data; -struct ep93xx_spi_info; - -void ep93xx_map_io(void); -void ep93xx_init_irq(void); - -void ep93xx_register_flash(unsigned int width, - resource_size_t start, resource_size_t size); - -void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); -void ep93xx_register_i2c(struct i2c_board_info *devices, int num); -void ep93xx_register_spi(struct ep93xx_spi_info *info, - struct spi_board_info *devices, int num); -void ep93xx_register_fb(struct ep93xxfb_mach_info *data); -void ep93xx_register_pwm(int pwm0, int pwm1); -void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data); -void ep93xx_register_i2s(void); -void ep93xx_register_ac97(void); -void ep93xx_register_ide(void); -void ep93xx_register_adc(void); - -struct device *ep93xx_init_devices(void); -extern void ep93xx_timer_init(void); - -void ep93xx_restart(enum reboot_mode, const char *); - -#endif diff --git a/arch/arm/mach-ep93xx/soc.h b/arch/arm/mach-ep93xx/soc.h deleted file mode 100644 index 3245ebbd5069..000000000000 --- a/arch/arm/mach-ep93xx/soc.h +++ /dev/null @@ -1,212 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * arch/arm/mach-ep93xx/soc.h - * - * Copyright (C) 2012 Open Kernel Labs - * Copyright (C) 2012 Ryan Mallon - */ - -#ifndef _EP93XX_SOC_H -#define _EP93XX_SOC_H - -#include "ep93xx-regs.h" -#include "irqs.h" - -/* - * EP93xx Physical Memory Map: - * - * The ASDO pin is sampled at system reset to select a synchronous or - * asynchronous boot configuration. When ASDO is "1" (i.e. pulled-up) - * the synchronous boot mode is selected. When ASDO is "0" (i.e - * pulled-down) the asynchronous boot mode is selected. - * - * In synchronous boot mode nSDCE3 is decoded starting at physical address - * 0x00000000 and nCS0 is decoded starting at 0xf0000000. For asynchronous - * boot mode they are swapped with nCS0 decoded at 0x00000000 ann nSDCE3 - * decoded at 0xf0000000. - * - * There is known errata for the EP93xx dealing with External Memory - * Configurations. Please refer to "AN273: EP93xx Silicon Rev E Design - * Guidelines" for more information. This document can be found at: - * - * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf - */ - -#define EP93XX_CS0_PHYS_BASE_ASYNC 0x00000000 /* ASDO Pin = 0 */ -#define EP93XX_SDCE3_PHYS_BASE_SYNC 0x00000000 /* ASDO Pin = 1 */ -#define EP93XX_CS1_PHYS_BASE 0x10000000 -#define EP93XX_CS2_PHYS_BASE 0x20000000 -#define EP93XX_CS3_PHYS_BASE 0x30000000 -#define EP93XX_PCMCIA_PHYS_BASE 0x40000000 -#define EP93XX_CS6_PHYS_BASE 0x60000000 -#define EP93XX_CS7_PHYS_BASE 0x70000000 -#define EP93XX_SDCE0_PHYS_BASE 0xc0000000 -#define EP93XX_SDCE1_PHYS_BASE 0xd0000000 -#define EP93XX_SDCE2_PHYS_BASE 0xe0000000 -#define EP93XX_SDCE3_PHYS_BASE_ASYNC 0xf0000000 /* ASDO Pin = 0 */ -#define EP93XX_CS0_PHYS_BASE_SYNC 0xf0000000 /* ASDO Pin = 1 */ - -/* AHB peripherals */ -#define EP93XX_DMA_BASE EP93XX_AHB_IOMEM(0x00000000) - -#define EP93XX_ETHERNET_PHYS_BASE EP93XX_AHB_PHYS(0x00010000) -#define EP93XX_ETHERNET_BASE EP93XX_AHB_IOMEM(0x00010000) - -#define EP93XX_USB_PHYS_BASE EP93XX_AHB_PHYS(0x00020000) -#define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000) - -#define EP93XX_RASTER_PHYS_BASE EP93XX_AHB_PHYS(0x00030000) -#define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000) - -#define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000) - -#define EP93XX_SDRAM_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00060000) - -#define EP93XX_PCMCIA_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00080000) - -#define EP93XX_BOOT_ROM_BASE EP93XX_AHB_IOMEM(0x00090000) - -#define EP93XX_IDE_PHYS_BASE EP93XX_AHB_PHYS(0x000a0000) -#define EP93XX_IDE_BASE EP93XX_AHB_IOMEM(0x000a0000) - -#define EP93XX_VIC1_BASE EP93XX_AHB_IOMEM(0x000b0000) - -#define EP93XX_VIC2_BASE EP93XX_AHB_IOMEM(0x000c0000) - -/* APB peripherals */ -#define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000) - -#define EP93XX_I2S_PHYS_BASE EP93XX_APB_PHYS(0x00020000) -#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000) - -#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) - -#define EP93XX_AAC_PHYS_BASE EP93XX_APB_PHYS(0x00080000) -#define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000) - -#define EP93XX_SPI_PHYS_BASE EP93XX_APB_PHYS(0x000a0000) -#define EP93XX_SPI_BASE EP93XX_APB_IOMEM(0x000a0000) - -#define EP93XX_IRDA_BASE EP93XX_APB_IOMEM(0x000b0000) - -#define EP93XX_KEY_MATRIX_PHYS_BASE EP93XX_APB_PHYS(0x000f0000) -#define EP93XX_KEY_MATRIX_BASE EP93XX_APB_IOMEM(0x000f0000) - -#define EP93XX_ADC_PHYS_BASE EP93XX_APB_PHYS(0x00100000) -#define EP93XX_ADC_BASE EP93XX_APB_IOMEM(0x00100000) -#define EP93XX_TOUCHSCREEN_BASE EP93XX_APB_IOMEM(0x00100000) - -#define EP93XX_PWM_PHYS_BASE EP93XX_APB_PHYS(0x00110000) -#define EP93XX_PWM_BASE EP93XX_APB_IOMEM(0x00110000) - -#define EP93XX_RTC_PHYS_BASE EP93XX_APB_PHYS(0x00120000) -#define EP93XX_RTC_BASE EP93XX_APB_IOMEM(0x00120000) - -#define EP93XX_WATCHDOG_PHYS_BASE EP93XX_APB_PHYS(0x00140000) -#define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000) - -/* System controller */ -#define EP93XX_SYSCON_BASE EP93XX_APB_IOMEM(0x00130000) -#define EP93XX_SYSCON_REG(x) (EP93XX_SYSCON_BASE + (x)) -#define EP93XX_SYSCON_POWER_STATE EP93XX_SYSCON_REG(0x00) -#define EP93XX_SYSCON_PWRCNT EP93XX_SYSCON_REG(0x04) -#define EP93XX_SYSCON_PWRCNT_FIR_EN (1<<31) -#define EP93XX_SYSCON_PWRCNT_UARTBAUD (1<<29) -#define EP93XX_SYSCON_PWRCNT_USH_EN 28 -#define EP93XX_SYSCON_PWRCNT_DMA_M2M1 27 -#define EP93XX_SYSCON_PWRCNT_DMA_M2M0 26 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P8 25 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P9 24 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P6 23 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P7 22 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P4 21 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P5 20 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P2 19 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P3 18 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P0 17 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P1 16 -#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08) -#define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c) -#define EP93XX_SYSCON_CLKSET1 EP93XX_SYSCON_REG(0x20) -#define EP93XX_SYSCON_CLKSET1_NBYP1 (1<<23) -#define EP93XX_SYSCON_CLKSET2 EP93XX_SYSCON_REG(0x24) -#define EP93XX_SYSCON_CLKSET2_NBYP2 (1<<19) -#define EP93XX_SYSCON_CLKSET2_PLL2_EN (1<<18) -#define EP93XX_SYSCON_DEVCFG EP93XX_SYSCON_REG(0x80) -#define EP93XX_SYSCON_DEVCFG_SWRST (1<<31) -#define EP93XX_SYSCON_DEVCFG_D1ONG (1<<30) -#define EP93XX_SYSCON_DEVCFG_D0ONG (1<<29) -#define EP93XX_SYSCON_DEVCFG_IONU2 (1<<28) -#define EP93XX_SYSCON_DEVCFG_GONK (1<<27) -#define EP93XX_SYSCON_DEVCFG_TONG (1<<26) -#define EP93XX_SYSCON_DEVCFG_MONG (1<<25) -#define EP93XX_SYSCON_DEVCFG_U3EN 24 -#define EP93XX_SYSCON_DEVCFG_CPENA (1<<23) -#define EP93XX_SYSCON_DEVCFG_A2ONG (1<<22) -#define EP93XX_SYSCON_DEVCFG_A1ONG (1<<21) -#define EP93XX_SYSCON_DEVCFG_U2EN 20 -#define EP93XX_SYSCON_DEVCFG_EXVC (1<<19) -#define EP93XX_SYSCON_DEVCFG_U1EN 18 -#define EP93XX_SYSCON_DEVCFG_TIN (1<<17) -#define EP93XX_SYSCON_DEVCFG_HC3IN (1<<15) -#define EP93XX_SYSCON_DEVCFG_HC3EN (1<<14) -#define EP93XX_SYSCON_DEVCFG_HC1IN (1<<13) -#define EP93XX_SYSCON_DEVCFG_HC1EN (1<<12) -#define EP93XX_SYSCON_DEVCFG_HONIDE (1<<11) -#define EP93XX_SYSCON_DEVCFG_GONIDE (1<<10) -#define EP93XX_SYSCON_DEVCFG_PONG (1<<9) -#define EP93XX_SYSCON_DEVCFG_EONIDE (1<<8) -#define EP93XX_SYSCON_DEVCFG_I2SONSSP (1<<7) -#define EP93XX_SYSCON_DEVCFG_I2SONAC97 (1<<6) -#define EP93XX_SYSCON_DEVCFG_RASONP3 (1<<4) -#define EP93XX_SYSCON_DEVCFG_RAS (1<<3) -#define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2) -#define EP93XX_SYSCON_DEVCFG_KEYS (1<<1) -#define EP93XX_SYSCON_DEVCFG_SHENA (1<<0) -#define EP93XX_SYSCON_VIDCLKDIV EP93XX_SYSCON_REG(0x84) -#define EP93XX_SYSCON_CLKDIV_ENABLE 15 -#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14) -#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13) -#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8 -#define EP93XX_SYSCON_I2SCLKDIV EP93XX_SYSCON_REG(0x8c) -#define EP93XX_SYSCON_I2SCLKDIV_SENA 31 -#define EP93XX_SYSCON_I2SCLKDIV_ORIDE (1<<29) -#define EP93XX_SYSCON_I2SCLKDIV_SPOL (1<<19) -#define EP93XX_I2SCLKDIV_SDIV (1 << 16) -#define EP93XX_I2SCLKDIV_LRDIV32 (0 << 17) -#define EP93XX_I2SCLKDIV_LRDIV64 (1 << 17) -#define EP93XX_I2SCLKDIV_LRDIV128 (2 << 17) -#define EP93XX_I2SCLKDIV_LRDIV_MASK (3 << 17) -#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90) -#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN 31 -#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV 16 -#define EP93XX_SYSCON_KEYTCHCLKDIV_KEN 15 -#define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV (1<<0) -#define EP93XX_SYSCON_SYSCFG EP93XX_SYSCON_REG(0x9c) -#define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000) -#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28) -#define EP93XX_SYSCON_SYSCFG_SBOOT (1<<8) -#define EP93XX_SYSCON_SYSCFG_LCSN7 (1<<7) -#define EP93XX_SYSCON_SYSCFG_LCSN6 (1<<6) -#define EP93XX_SYSCON_SYSCFG_LASDO (1<<5) -#define EP93XX_SYSCON_SYSCFG_LEEDA (1<<4) -#define EP93XX_SYSCON_SYSCFG_LEECLK (1<<3) -#define EP93XX_SYSCON_SYSCFG_LCSN2 (1<<1) -#define EP93XX_SYSCON_SYSCFG_LCSN1 (1<<0) -#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0) - -/* EP93xx System Controller software locked register write */ -void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg); -void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits); - -static inline void ep93xx_devcfg_set_bits(unsigned int bits) -{ - ep93xx_devcfg_set_clear(bits, 0x00); -} - -static inline void ep93xx_devcfg_clear_bits(unsigned int bits) -{ - ep93xx_devcfg_set_clear(0x00, bits); -} - -#endif /* _EP93XX_SOC_H */ diff --git a/arch/arm/mach-ep93xx/timer-ep93xx.c b/arch/arm/mach-ep93xx/timer-ep93xx.c deleted file mode 100644 index a9efa7bc2fa1..000000000000 --- a/arch/arm/mach-ep93xx/timer-ep93xx.c +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "soc.h" -#include "platform.h" - -/************************************************************************* - * Timer handling for EP93xx - ************************************************************************* - * The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and - * 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate - * an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz, - * is free-running, and can't generate interrupts. - * - * The 508 kHz timers are ideal for use for the timer interrupt, as the - * most common values of HZ divide 508 kHz nicely. We pick the 32 bit - * timer (timer 3) to get as long sleep intervals as possible when using - * CONFIG_NO_HZ. - * - * The higher clock rate of timer 4 makes it a better choice than the - * other timers for use as clock source and for sched_clock(), providing - * a stable 40 bit time base. - ************************************************************************* - */ -#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x)) -#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00) -#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04) -#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08) -#define EP93XX_TIMER123_CONTROL_ENABLE (1 << 7) -#define EP93XX_TIMER123_CONTROL_MODE (1 << 6) -#define EP93XX_TIMER123_CONTROL_CLKSEL (1 << 3) -#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c) -#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20) -#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24) -#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28) -#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c) -#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60) -#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64) -#define EP93XX_TIMER4_VALUE_HIGH_ENABLE (1 << 8) -#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80) -#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84) -#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88) -#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c) - -#define EP93XX_TIMER123_RATE 508469 -#define EP93XX_TIMER4_RATE 983040 - -static u64 notrace ep93xx_read_sched_clock(void) -{ - u64 ret; - - ret = readl(EP93XX_TIMER4_VALUE_LOW); - ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32); - return ret; -} - -static u64 ep93xx_clocksource_read(struct clocksource *c) -{ - u64 ret; - - ret = readl(EP93XX_TIMER4_VALUE_LOW); - ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32); - return (u64) ret; -} - -static int ep93xx_clkevt_set_next_event(unsigned long next, - struct clock_event_device *evt) -{ - /* Default mode: periodic, off, 508 kHz */ - u32 tmode = EP93XX_TIMER123_CONTROL_MODE | - EP93XX_TIMER123_CONTROL_CLKSEL; - - /* Clear timer */ - writel(tmode, EP93XX_TIMER3_CONTROL); - - /* Set next event */ - writel(next, EP93XX_TIMER3_LOAD); - writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE, - EP93XX_TIMER3_CONTROL); - return 0; -} - - -static int ep93xx_clkevt_shutdown(struct clock_event_device *evt) -{ - /* Disable timer */ - writel(0, EP93XX_TIMER3_CONTROL); - - return 0; -} - -static struct clock_event_device ep93xx_clockevent = { - .name = "timer1", - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_state_shutdown = ep93xx_clkevt_shutdown, - .set_state_oneshot = ep93xx_clkevt_shutdown, - .tick_resume = ep93xx_clkevt_shutdown, - .set_next_event = ep93xx_clkevt_set_next_event, - .rating = 300, -}; - -static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - /* Writing any value clears the timer interrupt */ - writel(1, EP93XX_TIMER3_CLEAR); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -void __init ep93xx_timer_init(void) -{ - int irq = IRQ_EP93XX_TIMER3; - unsigned long flags = IRQF_TIMER | IRQF_IRQPOLL; - - /* Enable and register clocksource and sched_clock on timer 4 */ - writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE, - EP93XX_TIMER4_VALUE_HIGH); - clocksource_mmio_init(NULL, "timer4", - EP93XX_TIMER4_RATE, 200, 40, - ep93xx_clocksource_read); - sched_clock_register(ep93xx_read_sched_clock, 40, - EP93XX_TIMER4_RATE); - - /* Set up clockevent on timer 3 */ - if (request_irq(irq, ep93xx_timer_interrupt, flags, "ep93xx timer", - &ep93xx_clockevent)) - pr_err("Failed to request irq %d (ep93xx timer)\n", irq); - clockevents_config_and_register(&ep93xx_clockevent, - EP93XX_TIMER123_RATE, - 1, - 0xffffffffU); -} diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c deleted file mode 100644 index 0bbdf587c685..000000000000 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ /dev/null @@ -1,422 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/ts72xx.c - * Technologic Systems TS72xx SBC support. - * - * Copyright (C) 2006 Lennert Buytenhek - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gpio-ep93xx.h" -#include "hardware.h" - -#include -#include -#include - -#include "soc.h" -#include "ts72xx.h" - -/************************************************************************* - * IO map - *************************************************************************/ -static struct map_desc ts72xx_io_desc[] __initdata = { - { - .virtual = (unsigned long)TS72XX_MODEL_VIRT_BASE, - .pfn = __phys_to_pfn(TS72XX_MODEL_PHYS_BASE), - .length = TS72XX_MODEL_SIZE, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)TS72XX_OPTIONS_VIRT_BASE, - .pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE), - .length = TS72XX_OPTIONS_SIZE, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)TS72XX_OPTIONS2_VIRT_BASE, - .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE), - .length = TS72XX_OPTIONS2_SIZE, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)TS72XX_CPLDVER_VIRT_BASE, - .pfn = __phys_to_pfn(TS72XX_CPLDVER_PHYS_BASE), - .length = TS72XX_CPLDVER_SIZE, - .type = MT_DEVICE, - } -}; - -static void __init ts72xx_map_io(void) -{ - ep93xx_map_io(); - iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc)); -} - - -/************************************************************************* - * NAND flash - *************************************************************************/ -#define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */ -#define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */ - -static void ts72xx_nand_hwcontrol(struct nand_chip *chip, - int cmd, unsigned int ctrl) -{ - if (ctrl & NAND_CTRL_CHANGE) { - void __iomem *addr = chip->legacy.IO_ADDR_R; - unsigned char bits; - - addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE); - - bits = __raw_readb(addr) & ~0x07; - bits |= (ctrl & NAND_NCE) << 2; /* bit 0 -> bit 2 */ - bits |= (ctrl & NAND_CLE); /* bit 1 -> bit 1 */ - bits |= (ctrl & NAND_ALE) >> 2; /* bit 2 -> bit 0 */ - - __raw_writeb(bits, addr); - } - - if (cmd != NAND_CMD_NONE) - __raw_writeb(cmd, chip->legacy.IO_ADDR_W); -} - -static int ts72xx_nand_device_ready(struct nand_chip *chip) -{ - void __iomem *addr = chip->legacy.IO_ADDR_R; - - addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE); - - return !!(__raw_readb(addr) & 0x20); -} - -#define TS72XX_BOOTROM_PART_SIZE (SZ_16K) -#define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M) - -static struct mtd_partition ts72xx_nand_parts[] = { - { - .name = "TS-BOOTROM", - .offset = 0, - .size = TS72XX_BOOTROM_PART_SIZE, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "Linux", - .offset = MTDPART_OFS_RETAIN, - .size = TS72XX_REDBOOT_PART_SIZE, - /* leave so much for last partition */ - }, { - .name = "RedBoot", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, -}; - -static struct platform_nand_data ts72xx_nand_data = { - .chip = { - .nr_chips = 1, - .chip_offset = 0, - .chip_delay = 15, - }, - .ctrl = { - .cmd_ctrl = ts72xx_nand_hwcontrol, - .dev_ready = ts72xx_nand_device_ready, - }, -}; - -static struct resource ts72xx_nand_resource[] = { - { - .start = 0, /* filled in later */ - .end = 0, /* filled in later */ - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device ts72xx_nand_flash = { - .name = "gen_nand", - .id = -1, - .dev.platform_data = &ts72xx_nand_data, - .resource = ts72xx_nand_resource, - .num_resources = ARRAY_SIZE(ts72xx_nand_resource), -}; - -static void __init ts72xx_register_flash(struct mtd_partition *parts, int n, - resource_size_t start) -{ - /* - * TS7200 has NOR flash all other TS72xx board have NAND flash. - */ - if (board_is_ts7200()) { - ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M); - } else { - ts72xx_nand_resource[0].start = start; - ts72xx_nand_resource[0].end = start + SZ_16M - 1; - - ts72xx_nand_data.chip.partitions = parts; - ts72xx_nand_data.chip.nr_partitions = n; - - platform_device_register(&ts72xx_nand_flash); - } -} - -/************************************************************************* - * RTC M48T86 - *************************************************************************/ -#define TS72XX_RTC_INDEX_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x00800000) -#define TS72XX_RTC_DATA_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x01700000) - -static struct resource ts72xx_rtc_resources[] = { - DEFINE_RES_MEM(TS72XX_RTC_INDEX_PHYS_BASE, 0x01), - DEFINE_RES_MEM(TS72XX_RTC_DATA_PHYS_BASE, 0x01), -}; - -static struct platform_device ts72xx_rtc_device = { - .name = "rtc-m48t86", - .id = -1, - .resource = ts72xx_rtc_resources, - .num_resources = ARRAY_SIZE(ts72xx_rtc_resources), -}; - -/************************************************************************* - * Watchdog (in CPLD) - *************************************************************************/ -#define TS72XX_WDT_CONTROL_PHYS_BASE (EP93XX_CS2_PHYS_BASE + 0x03800000) -#define TS72XX_WDT_FEED_PHYS_BASE (EP93XX_CS2_PHYS_BASE + 0x03c00000) - -static struct resource ts72xx_wdt_resources[] = { - DEFINE_RES_MEM(TS72XX_WDT_CONTROL_PHYS_BASE, 0x01), - DEFINE_RES_MEM(TS72XX_WDT_FEED_PHYS_BASE, 0x01), -}; - -static struct platform_device ts72xx_wdt_device = { - .name = "ts72xx-wdt", - .id = -1, - .resource = ts72xx_wdt_resources, - .num_resources = ARRAY_SIZE(ts72xx_wdt_resources), -}; - -/************************************************************************* - * ETH - *************************************************************************/ -static struct ep93xx_eth_data __initdata ts72xx_eth_data = { - .phy_id = 1, -}; - -/************************************************************************* - * SPI SD/MMC host - *************************************************************************/ -#define BK3_EN_SDCARD_PHYS_BASE 0x12400000 -#define BK3_EN_SDCARD_PWR 0x0 -#define BK3_DIS_SDCARD_PWR 0x0C -static void bk3_mmc_spi_setpower(struct device *dev, unsigned int vdd) -{ - void __iomem *pwr_sd = ioremap(BK3_EN_SDCARD_PHYS_BASE, SZ_4K); - - if (!pwr_sd) { - pr_err("Failed to enable SD card power!"); - return; - } - - pr_debug("%s: SD card pwr %s VDD:0x%x\n", __func__, - !!vdd ? "ON" : "OFF", vdd); - - if (!!vdd) - __raw_writeb(BK3_EN_SDCARD_PWR, pwr_sd); - else - __raw_writeb(BK3_DIS_SDCARD_PWR, pwr_sd); - - iounmap(pwr_sd); -} - -static struct mmc_spi_platform_data bk3_spi_mmc_data = { - .detect_delay = 500, - .powerup_msecs = 100, - .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, - .caps = MMC_CAP_NONREMOVABLE, - .setpower = bk3_mmc_spi_setpower, -}; - -/************************************************************************* - * SPI Bus - SD card access - *************************************************************************/ -static struct spi_board_info bk3_spi_board_info[] __initdata = { - { - .modalias = "mmc_spi", - .platform_data = &bk3_spi_mmc_data, - .max_speed_hz = 7.4E6, - .bus_num = 0, - .chip_select = 0, - .mode = SPI_MODE_0, - }, -}; - -/* - * This is a stub -> the FGPIO[3] pin is not connected on the schematic - * The all work is performed automatically by !SPI_FRAME (SFRM1) and - * goes through CPLD - */ -static struct gpiod_lookup_table bk3_spi_cs_gpio_table = { - .dev_id = "spi0", - .table = { - GPIO_LOOKUP("gpio-ep93xx.5", 3, "cs", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct ep93xx_spi_info bk3_spi_master __initdata = { - .use_dma = 1, -}; - -/************************************************************************* - * TS72XX support code - *************************************************************************/ -#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX) - -/* Relative to EP93XX_CS1_PHYS_BASE */ -#define TS73XX_FPGA_LOADER_BASE 0x03c00000 - -static struct resource ts73xx_fpga_resources[] = { - { - .start = EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE, - .end = EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE + 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device ts73xx_fpga_device = { - .name = "ts73xx-fpga-mgr", - .id = -1, - .resource = ts73xx_fpga_resources, - .num_resources = ARRAY_SIZE(ts73xx_fpga_resources), -}; - -#endif - -/************************************************************************* - * SPI Bus - *************************************************************************/ -static struct spi_board_info ts72xx_spi_devices[] __initdata = { - { - .modalias = "tmp122", - .max_speed_hz = 2 * 1000 * 1000, - .bus_num = 0, - .chip_select = 0, - }, -}; - -static struct gpiod_lookup_table ts72xx_spi_cs_gpio_table = { - .dev_id = "spi0", - .table = { - /* DIO_17 */ - GPIO_LOOKUP("gpio-ep93xx.5", 2, "cs", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct ep93xx_spi_info ts72xx_spi_info __initdata = { - /* Intentionally left blank */ -}; - -static void __init ts72xx_init_machine(void) -{ - ep93xx_init_devices(); - ts72xx_register_flash(ts72xx_nand_parts, ARRAY_SIZE(ts72xx_nand_parts), - is_ts9420_installed() ? - EP93XX_CS7_PHYS_BASE : EP93XX_CS6_PHYS_BASE); - platform_device_register(&ts72xx_rtc_device); - platform_device_register(&ts72xx_wdt_device); - - ep93xx_register_eth(&ts72xx_eth_data, 1); -#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX) - if (board_is_ts7300()) - platform_device_register(&ts73xx_fpga_device); -#endif - gpiod_add_lookup_table(&ts72xx_spi_cs_gpio_table); - ep93xx_register_spi(&ts72xx_spi_info, ts72xx_spi_devices, - ARRAY_SIZE(ts72xx_spi_devices)); -} - -MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") - /* Maintainer: Lennert Buytenhek */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ts72xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = ts72xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END - -/************************************************************************* - * EP93xx I2S audio peripheral handling - *************************************************************************/ -static struct resource ep93xx_i2s_resource[] = { - DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100), - DEFINE_RES_IRQ_NAMED(IRQ_EP93XX_SAI, "spilink i2s slave"), -}; - -static struct platform_device ep93xx_i2s_device = { - .name = "ep93xx-spilink-i2s", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_i2s_resource), - .resource = ep93xx_i2s_resource, -}; - -/************************************************************************* - * BK3 support code - *************************************************************************/ -static struct mtd_partition bk3_nand_parts[] = { - { - .name = "System", - .offset = 0x00000000, - .size = 0x01e00000, - }, { - .name = "Data", - .offset = 0x01e00000, - .size = 0x05f20000 - }, { - .name = "RedBoot", - .offset = 0x07d20000, - .size = 0x002e0000, - .mask_flags = MTD_WRITEABLE, /* force RO */ - }, -}; - -static void __init bk3_init_machine(void) -{ - ep93xx_init_devices(); - - ts72xx_register_flash(bk3_nand_parts, ARRAY_SIZE(bk3_nand_parts), - EP93XX_CS6_PHYS_BASE); - - ep93xx_register_eth(&ts72xx_eth_data, 1); - - gpiod_add_lookup_table(&bk3_spi_cs_gpio_table); - ep93xx_register_spi(&bk3_spi_master, bk3_spi_board_info, - ARRAY_SIZE(bk3_spi_board_info)); - - /* Configure ep93xx's I2S to use AC97 pins */ - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97); - platform_device_register(&ep93xx_i2s_device); -} - -MACHINE_START(BK3, "Liebherr controller BK3.1") - /* Maintainer: Lukasz Majewski */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ts72xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = bk3_init_machine, - .restart = ep93xx_restart, -MACHINE_END diff --git a/arch/arm/mach-ep93xx/ts72xx.h b/arch/arm/mach-ep93xx/ts72xx.h deleted file mode 100644 index 00b4941d29c9..000000000000 --- a/arch/arm/mach-ep93xx/ts72xx.h +++ /dev/null @@ -1,94 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * arch/arm/mach-ep93xx/include/mach/ts72xx.h - */ - -/* - * TS72xx memory map: - * - * virt phys size - * febff000 22000000 4K model number register (bits 0-2) - * febfe000 22400000 4K options register - * febfd000 22800000 4K options register #2 - * febfc000 23400000 4K CPLD version register - */ - -#ifndef __TS72XX_H_ -#define __TS72XX_H_ - -#define TS72XX_MODEL_PHYS_BASE 0x22000000 -#define TS72XX_MODEL_VIRT_BASE IOMEM(0xfebff000) -#define TS72XX_MODEL_SIZE 0x00001000 - -#define TS72XX_MODEL_TS7200 0x00 -#define TS72XX_MODEL_TS7250 0x01 -#define TS72XX_MODEL_TS7260 0x02 -#define TS72XX_MODEL_TS7300 0x03 -#define TS72XX_MODEL_TS7400 0x04 -#define TS72XX_MODEL_MASK 0x07 - - -#define TS72XX_OPTIONS_PHYS_BASE 0x22400000 -#define TS72XX_OPTIONS_VIRT_BASE IOMEM(0xfebfe000) -#define TS72XX_OPTIONS_SIZE 0x00001000 - -#define TS72XX_OPTIONS_COM2_RS485 0x02 -#define TS72XX_OPTIONS_MAX197 0x01 - - -#define TS72XX_OPTIONS2_PHYS_BASE 0x22800000 -#define TS72XX_OPTIONS2_VIRT_BASE IOMEM(0xfebfd000) -#define TS72XX_OPTIONS2_SIZE 0x00001000 - -#define TS72XX_OPTIONS2_TS9420 0x04 -#define TS72XX_OPTIONS2_TS9420_BOOT 0x02 - -#define TS72XX_CPLDVER_PHYS_BASE 0x23400000 -#define TS72XX_CPLDVER_VIRT_BASE IOMEM(0xfebfc000) -#define TS72XX_CPLDVER_SIZE 0x00001000 - -#ifndef __ASSEMBLY__ - -static inline int ts72xx_model(void) -{ - return __raw_readb(TS72XX_MODEL_VIRT_BASE) & TS72XX_MODEL_MASK; -} - -static inline int board_is_ts7200(void) -{ - return ts72xx_model() == TS72XX_MODEL_TS7200; -} - -static inline int board_is_ts7250(void) -{ - return ts72xx_model() == TS72XX_MODEL_TS7250; -} - -static inline int board_is_ts7260(void) -{ - return ts72xx_model() == TS72XX_MODEL_TS7260; -} - -static inline int board_is_ts7300(void) -{ - return ts72xx_model() == TS72XX_MODEL_TS7300; -} - -static inline int board_is_ts7400(void) -{ - return ts72xx_model() == TS72XX_MODEL_TS7400; -} - -static inline int is_max197_installed(void) -{ - return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) & - TS72XX_OPTIONS_MAX197); -} - -static inline int is_ts9420_installed(void) -{ - return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) & - TS72XX_OPTIONS2_TS9420); -} -#endif -#endif /* __TS72XX_H_ */ diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c deleted file mode 100644 index b3087b8eed3f..000000000000 --- a/arch/arm/mach-ep93xx/vision_ep9307.c +++ /dev/null @@ -1,321 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/vision_ep9307.c - * Vision Engraving Systems EP9307 SoM support. - * - * Copyright (C) 2008-2011 Vision Engraving Systems - * H Hartley Sweeten - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "hardware.h" -#include -#include -#include "gpio-ep93xx.h" - -#include -#include -#include - -#include "soc.h" - -/************************************************************************* - * Static I/O mappings for the FPGA - *************************************************************************/ -#define VISION_PHYS_BASE EP93XX_CS7_PHYS_BASE -#define VISION_VIRT_BASE 0xfebff000 - -static struct map_desc vision_io_desc[] __initdata = { - { - .virtual = VISION_VIRT_BASE, - .pfn = __phys_to_pfn(VISION_PHYS_BASE), - .length = SZ_4K, - .type = MT_DEVICE, - }, -}; - -static void __init vision_map_io(void) -{ - ep93xx_map_io(); - - iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc)); -} - -/************************************************************************* - * Ethernet - *************************************************************************/ -static struct ep93xx_eth_data vision_eth_data __initdata = { - .phy_id = 1, -}; - -/************************************************************************* - * Framebuffer - *************************************************************************/ -#define VISION_LCD_ENABLE EP93XX_GPIO_LINE_EGPIO1 - -static int vision_lcd_setup(struct platform_device *pdev) -{ - int err; - - err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH, - dev_name(&pdev->dev)); - if (err) - return err; - - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS | - EP93XX_SYSCON_DEVCFG_RASONP3 | - EP93XX_SYSCON_DEVCFG_EXVC); - - return 0; -} - -static void vision_lcd_teardown(struct platform_device *pdev) -{ - gpio_free(VISION_LCD_ENABLE); -} - -static void vision_lcd_blank(int blank_mode, struct fb_info *info) -{ - if (blank_mode) - gpio_set_value(VISION_LCD_ENABLE, 0); - else - gpio_set_value(VISION_LCD_ENABLE, 1); -} - -static struct ep93xxfb_mach_info ep93xxfb_info __initdata = { - .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, - .setup = vision_lcd_setup, - .teardown = vision_lcd_teardown, - .blank = vision_lcd_blank, -}; - - -/************************************************************************* - * GPIO Expanders - *************************************************************************/ -#define PCA9539_74_GPIO_BASE (EP93XX_GPIO_LINE_MAX + 1) -#define PCA9539_75_GPIO_BASE (PCA9539_74_GPIO_BASE + 16) -#define PCA9539_76_GPIO_BASE (PCA9539_75_GPIO_BASE + 16) -#define PCA9539_77_GPIO_BASE (PCA9539_76_GPIO_BASE + 16) - -static struct pca953x_platform_data pca953x_74_gpio_data = { - .gpio_base = PCA9539_74_GPIO_BASE, - .irq_base = EP93XX_BOARD_IRQ(0), -}; - -static struct pca953x_platform_data pca953x_75_gpio_data = { - .gpio_base = PCA9539_75_GPIO_BASE, - .irq_base = -1, -}; - -static struct pca953x_platform_data pca953x_76_gpio_data = { - .gpio_base = PCA9539_76_GPIO_BASE, - .irq_base = -1, -}; - -static struct pca953x_platform_data pca953x_77_gpio_data = { - .gpio_base = PCA9539_77_GPIO_BASE, - .irq_base = -1, -}; - -/************************************************************************* - * I2C Bus - *************************************************************************/ - -static struct i2c_board_info vision_i2c_info[] __initdata = { - { - I2C_BOARD_INFO("isl1208", 0x6f), - .irq = IRQ_EP93XX_EXT1, - }, { - I2C_BOARD_INFO("pca9539", 0x74), - .platform_data = &pca953x_74_gpio_data, - }, { - I2C_BOARD_INFO("pca9539", 0x75), - .platform_data = &pca953x_75_gpio_data, - }, { - I2C_BOARD_INFO("pca9539", 0x76), - .platform_data = &pca953x_76_gpio_data, - }, { - I2C_BOARD_INFO("pca9539", 0x77), - .platform_data = &pca953x_77_gpio_data, - }, -}; - -/************************************************************************* - * SPI CS4271 Audio Codec - *************************************************************************/ -static struct cs4271_platform_data vision_cs4271_data = { - /* Intentionally left blank */ -}; - -/************************************************************************* - * SPI Flash - *************************************************************************/ -static struct mtd_partition vision_spi_flash_partitions[] = { - { - .name = "SPI bootstrap", - .offset = 0, - .size = SZ_4K, - }, { - .name = "Bootstrap config", - .offset = MTDPART_OFS_APPEND, - .size = SZ_4K, - }, { - .name = "System config", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - }, -}; - -static struct flash_platform_data vision_spi_flash_data = { - .name = "SPI Flash", - .parts = vision_spi_flash_partitions, - .nr_parts = ARRAY_SIZE(vision_spi_flash_partitions), -}; - -/************************************************************************* - * SPI SD/MMC host - *************************************************************************/ -static struct mmc_spi_platform_data vision_spi_mmc_data = { - .detect_delay = 100, - .powerup_msecs = 100, - .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, - .caps2 = MMC_CAP2_RO_ACTIVE_HIGH, -}; - -static struct gpiod_lookup_table vision_spi_mmc_gpio_table = { - .dev_id = "mmc_spi.2", /* "mmc_spi @ CS2 */ - .table = { - /* Card detect */ - GPIO_LOOKUP_IDX("gpio-ep93xx.1", 7, NULL, 0, GPIO_ACTIVE_LOW), - /* Write protect */ - GPIO_LOOKUP_IDX("gpio-ep93xx.5", 0, NULL, 1, GPIO_ACTIVE_HIGH), - { }, - }, -}; - -/************************************************************************* - * SPI Bus - *************************************************************************/ -static struct spi_board_info vision_spi_board_info[] __initdata = { - { - .modalias = "cs4271", - .platform_data = &vision_cs4271_data, - .max_speed_hz = 6000000, - .bus_num = 0, - .chip_select = 0, - .mode = SPI_MODE_3, - }, { - .modalias = "sst25l", - .platform_data = &vision_spi_flash_data, - .max_speed_hz = 20000000, - .bus_num = 0, - .chip_select = 1, - .mode = SPI_MODE_3, - }, { - .modalias = "mmc_spi", - .platform_data = &vision_spi_mmc_data, - .max_speed_hz = 20000000, - .bus_num = 0, - .chip_select = 2, - .mode = SPI_MODE_3, - }, -}; - -static struct gpiod_lookup_table vision_spi_cs4271_gpio_table = { - .dev_id = "spi0.0", /* cs4271 @ CS0 */ - .table = { - /* RESET */ - GPIO_LOOKUP_IDX("H", 2, NULL, 0, GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct gpiod_lookup_table vision_spi_cs_gpio_table = { - .dev_id = "spi0", - .table = { - GPIO_LOOKUP_IDX("gpio-ep93xx.0", 6, "cs", 0, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("gpio-ep93xx.0", 7, "cs", 1, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("gpio-ep93xx.6", 2, "cs", 2, GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct ep93xx_spi_info vision_spi_master __initdata = { - .use_dma = 1, -}; - -/************************************************************************* - * I2S Audio - *************************************************************************/ -static struct platform_device vision_audio_device = { - .name = "edb93xx-audio", - .id = -1, -}; - -static void __init vision_register_i2s(void) -{ - ep93xx_register_i2s(); - platform_device_register(&vision_audio_device); -} - -/************************************************************************* - * Machine Initialization - *************************************************************************/ -static void __init vision_init_machine(void) -{ - ep93xx_init_devices(); - ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M); - ep93xx_register_eth(&vision_eth_data, 1); - ep93xx_register_fb(&ep93xxfb_info); - ep93xx_register_pwm(1, 0); - - /* - * Request the gpio expander's interrupt gpio line now to prevent - * the kernel from doing a WARN in gpiolib:gpio_ensure_requested(). - */ - if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN, - "pca9539:74")) - pr_warn("cannot request interrupt gpio for pca9539:74\n"); - - vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7)); - - ep93xx_register_i2c(vision_i2c_info, - ARRAY_SIZE(vision_i2c_info)); - gpiod_add_lookup_table(&vision_spi_cs4271_gpio_table); - gpiod_add_lookup_table(&vision_spi_mmc_gpio_table); - gpiod_add_lookup_table(&vision_spi_cs_gpio_table); - ep93xx_register_spi(&vision_spi_master, vision_spi_board_info, - ARRAY_SIZE(vision_spi_board_info)); - vision_register_i2s(); -} - -MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307") - /* Maintainer: H Hartley Sweeten */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS + EP93XX_BOARD_IRQS, - .map_io = vision_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = vision_init_machine, - .restart = ep93xx_restart, -MACHINE_END diff --git a/include/linux/platform_data/spi-ep93xx.h b/include/linux/platform_data/spi-ep93xx.h deleted file mode 100644 index b439f2a896e0..000000000000 --- a/include/linux/platform_data/spi-ep93xx.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_MACH_EP93XX_SPI_H -#define __ASM_MACH_EP93XX_SPI_H - -struct spi_device; - -/** - * struct ep93xx_spi_info - EP93xx specific SPI descriptor - * @use_dma: use DMA for the transfers - */ -struct ep93xx_spi_info { - bool use_dma; -}; - -#endif /* __ASM_MACH_EP93XX_SPI_H */ -- cgit v1.2.3 From 43528a72526152f17a918973b3b8b6f383b90f98 Mon Sep 17 00:00:00 2001 From: Nikita Shubin Date: Mon, 9 Sep 2024 11:11:01 +0300 Subject: ARM: ep93xx: soc: drop defines Remove unnecessary defines, as we dropped board files. Signed-off-by: Nikita Shubin Tested-by: Alexander Sverdlin Acked-by: Vinod Koul Signed-off-by: Arnd Bergmann --- include/linux/platform_data/eth-ep93xx.h | 10 --------- include/linux/platform_data/keypad-ep93xx.h | 32 ----------------------------- include/linux/soc/cirrus/ep93xx.h | 13 ------------ 3 files changed, 55 deletions(-) delete mode 100644 include/linux/platform_data/eth-ep93xx.h delete mode 100644 include/linux/platform_data/keypad-ep93xx.h (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/eth-ep93xx.h b/include/linux/platform_data/eth-ep93xx.h deleted file mode 100644 index 8eef637a804d..000000000000 --- a/include/linux/platform_data/eth-ep93xx.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _LINUX_PLATFORM_DATA_ETH_EP93XX -#define _LINUX_PLATFORM_DATA_ETH_EP93XX - -struct ep93xx_eth_data { - unsigned char dev_addr[6]; - unsigned char phy_id; -}; - -#endif diff --git a/include/linux/platform_data/keypad-ep93xx.h b/include/linux/platform_data/keypad-ep93xx.h deleted file mode 100644 index 3054fced8509..000000000000 --- a/include/linux/platform_data/keypad-ep93xx.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __KEYPAD_EP93XX_H -#define __KEYPAD_EP93XX_H - -struct matrix_keymap_data; - -/* flags for the ep93xx_keypad driver */ -#define EP93XX_KEYPAD_DISABLE_3_KEY (1<<0) /* disable 3-key reset */ -#define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */ -#define EP93XX_KEYPAD_BACK_DRIVE (1<<2) /* back driving mode */ -#define EP93XX_KEYPAD_TEST_MODE (1<<3) /* scan only column 0 */ -#define EP93XX_KEYPAD_AUTOREPEAT (1<<4) /* enable key autorepeat */ - -/** - * struct ep93xx_keypad_platform_data - platform specific device structure - * @keymap_data: pointer to &matrix_keymap_data - * @debounce: debounce start count; terminal count is 0xff - * @prescale: row/column counter pre-scaler load value - * @flags: see above - */ -struct ep93xx_keypad_platform_data { - struct matrix_keymap_data *keymap_data; - unsigned int debounce; - unsigned int prescale; - unsigned int flags; - unsigned int clk_rate; -}; - -#define EP93XX_MATRIX_ROWS (8) -#define EP93XX_MATRIX_COLS (8) - -#endif /* __KEYPAD_EP93XX_H */ diff --git a/include/linux/soc/cirrus/ep93xx.h b/include/linux/soc/cirrus/ep93xx.h index 142c33a2d7db..3e6cf2b25a97 100644 --- a/include/linux/soc/cirrus/ep93xx.h +++ b/include/linux/soc/cirrus/ep93xx.h @@ -2,7 +2,6 @@ #ifndef _SOC_EP93XX_H #define _SOC_EP93XX_H -struct platform_device; struct regmap; struct spinlock_t; @@ -36,16 +35,4 @@ struct ep93xx_regmap_adev { #define to_ep93xx_regmap_adev(_adev) \ container_of((_adev), struct ep93xx_regmap_adev, adev) -#ifdef CONFIG_ARCH_EP93XX -int ep93xx_i2s_acquire(void); -void ep93xx_i2s_release(void); -unsigned int ep93xx_chip_revision(void); - -#else -static inline int ep93xx_i2s_acquire(void) { return 0; } -static inline void ep93xx_i2s_release(void) {} -static inline unsigned int ep93xx_chip_revision(void) { return 0; } - -#endif - #endif -- cgit v1.2.3 From a015b1828653b591de0aa5303c0dbc4235935f94 Mon Sep 17 00:00:00 2001 From: Nikita Shubin Date: Mon, 9 Sep 2024 11:11:03 +0300 Subject: dmaengine: cirrus: remove platform code Remove DMA platform header, from now on we use device tree for DMA clients. Acked-by: Vinod Koul Signed-off-by: Nikita Shubin Tested-by: Alexander Sverdlin Signed-off-by: Arnd Bergmann --- drivers/dma/ep93xx_dma.c | 48 ++++++++++++++- include/linux/platform_data/dma-ep93xx.h | 100 ------------------------------- 2 files changed, 46 insertions(+), 102 deletions(-) delete mode 100644 include/linux/platform_data/dma-ep93xx.h (limited to 'include/linux/platform_data') diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index 17c8e2badee2..43c4241af7f5 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -25,8 +26,6 @@ #include #include -#include - #include "dmaengine.h" /* M2P registers */ @@ -106,6 +105,26 @@ #define DMA_MAX_CHAN_BYTES 0xffff #define DMA_MAX_CHAN_DESCRIPTORS 32 +/* + * M2P channels. + * + * Note that these values are also directly used for setting the PPALLOC + * register. + */ +#define EP93XX_DMA_I2S1 0 +#define EP93XX_DMA_I2S2 1 +#define EP93XX_DMA_AAC1 2 +#define EP93XX_DMA_AAC2 3 +#define EP93XX_DMA_AAC3 4 +#define EP93XX_DMA_I2S3 5 +#define EP93XX_DMA_UART1 6 +#define EP93XX_DMA_UART2 7 +#define EP93XX_DMA_UART3 8 +#define EP93XX_DMA_IRDA 9 +/* M2M channels */ +#define EP93XX_DMA_SSP 10 +#define EP93XX_DMA_IDE 11 + enum ep93xx_dma_type { M2P_DMA, M2M_DMA, @@ -242,6 +261,31 @@ static struct ep93xx_dma_chan *to_ep93xx_dma_chan(struct dma_chan *chan) return container_of(chan, struct ep93xx_dma_chan, chan); } +static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan) +{ + if (device_is_compatible(chan->device->dev, "cirrus,ep9301-dma-m2p")) + return true; + + return !strcmp(dev_name(chan->device->dev), "ep93xx-dma-m2p"); +} + +/* + * ep93xx_dma_chan_direction - returns direction the channel can be used + * + * This function can be used in filter functions to find out whether the + * channel supports given DMA direction. Only M2P channels have such + * limitation, for M2M channels the direction is configurable. + */ +static inline enum dma_transfer_direction +ep93xx_dma_chan_direction(struct dma_chan *chan) +{ + if (!ep93xx_dma_chan_is_m2p(chan)) + return DMA_TRANS_NONE; + + /* even channels are for TX, odd for RX */ + return (chan->chan_id % 2 == 0) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; +} + /** * ep93xx_dma_set_active - set new active descriptor chain * @edmac: channel diff --git a/include/linux/platform_data/dma-ep93xx.h b/include/linux/platform_data/dma-ep93xx.h deleted file mode 100644 index 9ec5cdd5a1eb..000000000000 --- a/include/linux/platform_data/dma-ep93xx.h +++ /dev/null @@ -1,100 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -#include -#include -#include -#include -#include -#include - -/* - * M2P channels. - * - * Note that these values are also directly used for setting the PPALLOC - * register. - */ -#define EP93XX_DMA_I2S1 0 -#define EP93XX_DMA_I2S2 1 -#define EP93XX_DMA_AAC1 2 -#define EP93XX_DMA_AAC2 3 -#define EP93XX_DMA_AAC3 4 -#define EP93XX_DMA_I2S3 5 -#define EP93XX_DMA_UART1 6 -#define EP93XX_DMA_UART2 7 -#define EP93XX_DMA_UART3 8 -#define EP93XX_DMA_IRDA 9 -/* M2M channels */ -#define EP93XX_DMA_SSP 10 -#define EP93XX_DMA_IDE 11 - -/** - * struct ep93xx_dma_data - configuration data for the EP93xx dmaengine - * @port: peripheral which is requesting the channel - * @direction: TX/RX channel - * @name: optional name for the channel, this is displayed in /proc/interrupts - * - * This information is passed as private channel parameter in a filter - * function. Note that this is only needed for slave/cyclic channels. For - * memcpy channels %NULL data should be passed. - */ -struct ep93xx_dma_data { - int port; - enum dma_transfer_direction direction; - const char *name; -}; - -/** - * struct ep93xx_dma_chan_data - platform specific data for a DMA channel - * @name: name of the channel, used for getting the right clock for the channel - * @base: mapped registers - * @irq: interrupt number used by this channel - */ -struct ep93xx_dma_chan_data { - const char *name; - void __iomem *base; - int irq; -}; - -/** - * struct ep93xx_dma_platform_data - platform data for the dmaengine driver - * @channels: array of channels which are passed to the driver - * @num_channels: number of channels in the array - * - * This structure is passed to the DMA engine driver via platform data. For - * M2P channels, contract is that even channels are for TX and odd for RX. - * There is no requirement for the M2M channels. - */ -struct ep93xx_dma_platform_data { - struct ep93xx_dma_chan_data *channels; - size_t num_channels; -}; - -static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan) -{ - if (device_is_compatible(chan->device->dev, "cirrus,ep9301-dma-m2p")) - return true; - - return !strcmp(dev_name(chan->device->dev), "ep93xx-dma-m2p"); -} - -/** - * ep93xx_dma_chan_direction - returns direction the channel can be used - * @chan: channel - * - * This function can be used in filter functions to find out whether the - * channel supports given DMA direction. Only M2P channels have such - * limitation, for M2M channels the direction is configurable. - */ -static inline enum dma_transfer_direction -ep93xx_dma_chan_direction(struct dma_chan *chan) -{ - if (!ep93xx_dma_chan_is_m2p(chan)) - return DMA_TRANS_NONE; - - /* even channels are for TX, odd for RX */ - return (chan->chan_id % 2 == 0) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; -} - -#endif /* __ASM_ARCH_DMA_H */ -- cgit v1.2.3 From 0f702757c68b9790a844e5c07073d3d1c777b13a Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Mon, 26 Aug 2024 11:34:11 +0800 Subject: ARM: samsung: Remove obsoleted declaration for s3c_hwmon_set_platdata The s3c_hwmon_set_platdata() have been removed since commit 0d297df03890 ("ARM: s3c: simplify platform code"), and now it is useless, so remove it. Signed-off-by: Gaosheng Cui Link: https://lore.kernel.org/r/20240826033411.4022822-1-cuigaosheng1@huawei.com Signed-off-by: Krzysztof Kozlowski --- include/linux/platform_data/hwmon-s3c.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/hwmon-s3c.h b/include/linux/platform_data/hwmon-s3c.h index 1707ad4147df..7d21e0c41037 100644 --- a/include/linux/platform_data/hwmon-s3c.h +++ b/include/linux/platform_data/hwmon-s3c.h @@ -33,14 +33,4 @@ struct s3c_hwmon_pdata { struct s3c_hwmon_chcfg *in[8]; }; -/** - * s3c_hwmon_set_platdata - Set platform data for S3C HWMON device - * @pd: Platform data to register to device. - * - * Register the given platform data for use with the S3C HWMON device. - * The call will copy the platform data, so the board definitions can - * make the structure itself __initdata. - */ -extern void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd); - #endif /* __HWMON_S3C_H__ */ -- cgit v1.2.3 From 3a6ad95d97eb62a7b7c804ef7eeb329a1f697d00 Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Mon, 26 Aug 2024 11:31:18 +0800 Subject: ASoC: samsung: Remove obsoleted declaration for s3c64xx_ac97_setup_gpio The s3c64xx_ac97_setup_gpio() have been removed since commit 0d297df03890 ("ARM: s3c: simplify platform code"), and now it is useless, so remove it. Signed-off-by: Gaosheng Cui Link: https://lore.kernel.org/r/20240826033118.4021727-1-cuigaosheng1@huawei.com Signed-off-by: Krzysztof Kozlowski --- include/linux/platform_data/asoc-s3c.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/asoc-s3c.h b/include/linux/platform_data/asoc-s3c.h index f9c00f839e9f..085dd8e8af76 100644 --- a/include/linux/platform_data/asoc-s3c.h +++ b/include/linux/platform_data/asoc-s3c.h @@ -13,8 +13,6 @@ #include -extern void s3c64xx_ac97_setup_gpio(int); - struct samsung_i2s_type { /* If the Primary DAI has 5.1 Channels */ #define QUIRK_PRI_6CHAN (1 << 0) -- cgit v1.2.3 From 066c779b094b63754e0742ad8675d72d6c0a46f6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 3 Oct 2024 18:48:19 +0300 Subject: platform/x86: intel_scu_ipc: Don't use "proxy" headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update header inclusions to follow IWYU (Include What You Use) principle. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg Link: https://lore.kernel.org/r/20241003154819.1075141-1-andriy.shevchenko@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- include/linux/platform_data/x86/intel_scu_ipc.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/x86/intel_scu_ipc.h b/include/linux/platform_data/x86/intel_scu_ipc.h index 0ca9962e97f2..b287627759f7 100644 --- a/include/linux/platform_data/x86/intel_scu_ipc.h +++ b/include/linux/platform_data/x86/intel_scu_ipc.h @@ -2,9 +2,13 @@ #ifndef __PLATFORM_X86_INTEL_SCU_IPC_H_ #define __PLATFORM_X86_INTEL_SCU_IPC_H_ +#include #include +#include struct device; +struct module; + struct intel_scu_ipc_dev; /** -- cgit v1.2.3 From 95397784be23f66c5d4280b0a4c4e0d1ee74f2ef Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 2 Sep 2024 10:42:31 +0200 Subject: media: staging: drop omap4iss The omap4 camera driver has seen no progress since forever, and now OMAP4 support has also been dropped from u-boot (1). So it is time to retire this driver. (1): https://lists.denx.de/pipermail/u-boot/2024-July/558846.html Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart --- Documentation/admin-guide/media/omap4_camera.rst | 62 - Documentation/admin-guide/media/v4l-drivers.rst | 1 - MAINTAINERS | 8 - drivers/staging/media/Kconfig | 2 - drivers/staging/media/Makefile | 1 - drivers/staging/media/omap4iss/Kconfig | 12 - drivers/staging/media/omap4iss/Makefile | 9 - drivers/staging/media/omap4iss/TODO | 3 - drivers/staging/media/omap4iss/iss.c | 1354 --------------------- drivers/staging/media/omap4iss/iss.h | 247 ---- drivers/staging/media/omap4iss/iss_csi2.c | 1379 ---------------------- drivers/staging/media/omap4iss/iss_csi2.h | 155 --- drivers/staging/media/omap4iss/iss_csiphy.c | 277 ----- drivers/staging/media/omap4iss/iss_csiphy.h | 47 - drivers/staging/media/omap4iss/iss_ipipe.c | 579 --------- drivers/staging/media/omap4iss/iss_ipipe.h | 63 - drivers/staging/media/omap4iss/iss_ipipeif.c | 844 ------------- drivers/staging/media/omap4iss/iss_ipipeif.h | 89 -- drivers/staging/media/omap4iss/iss_regs.h | 899 -------------- drivers/staging/media/omap4iss/iss_resizer.c | 884 -------------- drivers/staging/media/omap4iss/iss_resizer.h | 72 -- drivers/staging/media/omap4iss/iss_video.c | 1274 -------------------- drivers/staging/media/omap4iss/iss_video.h | 203 ---- include/linux/platform_data/media/omap4iss.h | 66 -- 24 files changed, 8530 deletions(-) delete mode 100644 Documentation/admin-guide/media/omap4_camera.rst delete mode 100644 drivers/staging/media/omap4iss/Kconfig delete mode 100644 drivers/staging/media/omap4iss/Makefile delete mode 100644 drivers/staging/media/omap4iss/TODO delete mode 100644 drivers/staging/media/omap4iss/iss.c delete mode 100644 drivers/staging/media/omap4iss/iss.h delete mode 100644 drivers/staging/media/omap4iss/iss_csi2.c delete mode 100644 drivers/staging/media/omap4iss/iss_csi2.h delete mode 100644 drivers/staging/media/omap4iss/iss_csiphy.c delete mode 100644 drivers/staging/media/omap4iss/iss_csiphy.h delete mode 100644 drivers/staging/media/omap4iss/iss_ipipe.c delete mode 100644 drivers/staging/media/omap4iss/iss_ipipe.h delete mode 100644 drivers/staging/media/omap4iss/iss_ipipeif.c delete mode 100644 drivers/staging/media/omap4iss/iss_ipipeif.h delete mode 100644 drivers/staging/media/omap4iss/iss_regs.h delete mode 100644 drivers/staging/media/omap4iss/iss_resizer.c delete mode 100644 drivers/staging/media/omap4iss/iss_resizer.h delete mode 100644 drivers/staging/media/omap4iss/iss_video.c delete mode 100644 drivers/staging/media/omap4iss/iss_video.h delete mode 100644 include/linux/platform_data/media/omap4iss.h (limited to 'include/linux/platform_data') diff --git a/Documentation/admin-guide/media/omap4_camera.rst b/Documentation/admin-guide/media/omap4_camera.rst deleted file mode 100644 index 2ada9b1e6897..000000000000 --- a/Documentation/admin-guide/media/omap4_camera.rst +++ /dev/null @@ -1,62 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -OMAP4 ISS Driver -================ - -Author: Sergio Aguirre - -Copyright (C) 2012, Texas Instruments - -Introduction ------------- - -The OMAP44XX family of chips contains the Imaging SubSystem (a.k.a. ISS), -Which contains several components that can be categorized in 3 big groups: - -- Interfaces (2 Interfaces: CSI2-A & CSI2-B/CCP2) -- ISP (Image Signal Processor) -- SIMCOP (Still Image Coprocessor) - -For more information, please look in [#f1]_ for latest version of: -"OMAP4430 Multimedia Device Silicon Revision 2.x" - -As of Revision AB, the ISS is described in detail in section 8. - -This driver is supporting **only** the CSI2-A/B interfaces for now. - -It makes use of the Media Controller framework [#f2]_, and inherited most of the -code from OMAP3 ISP driver (found under drivers/media/platform/ti/omap3isp/\*), -except that it doesn't need an IOMMU now for ISS buffers memory mapping. - -Supports usage of MMAP buffers only (for now). - -Tested platforms ----------------- - -- OMAP4430SDP, w/ ES2.1 GP & SEVM4430-CAM-V1-0 (Contains IMX060 & OV5640, in - which only the last one is supported, outputting YUV422 frames). - -- TI Blaze MDP, w/ OMAP4430 ES2.2 EMU (Contains 1 IMX060 & 2 OV5650 sensors, in - which only the OV5650 are supported, outputting RAW10 frames). - -- PandaBoard, Rev. A2, w/ OMAP4430 ES2.1 GP & OV adapter board, tested with - following sensors: - * OV5640 - * OV5650 - -- Tested on mainline kernel: - - http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=summary - - Tag: v3.3 (commit c16fa4f2ad19908a47c63d8fa436a1178438c7e7) - -File list ---------- -drivers/staging/media/omap4iss/ -include/linux/platform_data/media/omap4iss.h - -References ----------- - -.. [#f1] http://focus.ti.com/general/docs/wtbu/wtbudocumentcenter.tsp?navigationId=12037&templateId=6123#62 -.. [#f2] http://lwn.net/Articles/420485/ diff --git a/Documentation/admin-guide/media/v4l-drivers.rst b/Documentation/admin-guide/media/v4l-drivers.rst index b6af448b9fe9..7d9029bbf109 100644 --- a/Documentation/admin-guide/media/v4l-drivers.rst +++ b/Documentation/admin-guide/media/v4l-drivers.rst @@ -20,7 +20,6 @@ Video4Linux (V4L) driver-specific documentation ivtv mgb4 omap3isp - omap4_camera philips qcom_camss raspberrypi-pisp-be diff --git a/MAINTAINERS b/MAINTAINERS index c27f3190737f..251ae8a52066 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16932,14 +16932,6 @@ S: Maintained F: Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml F: drivers/i2c/busses/i2c-omap.c -OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS) -M: Laurent Pinchart -L: linux-media@vger.kernel.org -S: Maintained -F: Documentation/devicetree/bindings/media/ti,omap3isp.txt -F: drivers/media/platform/ti/omap3isp/ -F: drivers/staging/media/omap4iss/ - OMAP MMC SUPPORT M: Aaro Koskinen L: linux-omap@vger.kernel.org diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 554c2e475ce3..b44214854399 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -32,8 +32,6 @@ source "drivers/staging/media/max96712/Kconfig" source "drivers/staging/media/meson/vdec/Kconfig" -source "drivers/staging/media/omap4iss/Kconfig" - source "drivers/staging/media/rkvdec/Kconfig" source "drivers/staging/media/starfive/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index dcaeeca0ee6d..ad4e9619a9e0 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -4,7 +4,6 @@ obj-$(CONFIG_INTEL_ATOMISP) += atomisp/ obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/ obj-$(CONFIG_VIDEO_MAX96712) += max96712/ obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/ -obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/ obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive/ obj-$(CONFIG_VIDEO_SUNXI) += sunxi/ diff --git a/drivers/staging/media/omap4iss/Kconfig b/drivers/staging/media/omap4iss/Kconfig deleted file mode 100644 index 6d1f55b09132..000000000000 --- a/drivers/staging/media/omap4iss/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -config VIDEO_OMAP4 - tristate "OMAP 4 Camera support" - depends on VIDEO_DEV && I2C - depends on ARCH_OMAP4 || COMPILE_TEST - select MEDIA_CONTROLLER - select VIDEO_V4L2_SUBDEV_API - select MFD_SYSCON - select VIDEOBUF2_DMA_CONTIG - help - Driver for an OMAP 4 ISS controller. diff --git a/drivers/staging/media/omap4iss/Makefile b/drivers/staging/media/omap4iss/Makefile deleted file mode 100644 index e64d489a4a76..000000000000 --- a/drivers/staging/media/omap4iss/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for OMAP4 ISS driver -# - -omap4-iss-objs += \ - iss.o iss_csi2.o iss_csiphy.o iss_ipipeif.o iss_ipipe.o iss_resizer.o iss_video.o - -obj-$(CONFIG_VIDEO_OMAP4) += omap4-iss.o diff --git a/drivers/staging/media/omap4iss/TODO b/drivers/staging/media/omap4iss/TODO deleted file mode 100644 index 4d220ef82653..000000000000 --- a/drivers/staging/media/omap4iss/TODO +++ /dev/null @@ -1,3 +0,0 @@ -* Fix FIFO/buffer overflows and underflows -* Replace dummy resizer code with a real implementation -* Fix checkpatch errors and warnings diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c deleted file mode 100644 index 0c4283bb48ad..000000000000 --- a/drivers/staging/media/omap4iss/iss.c +++ /dev/null @@ -1,1354 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * TI OMAP4 ISS V4L2 Driver - * - * Copyright (C) 2012, Texas Instruments - * - * Author: Sergio Aguirre - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "iss.h" -#include "iss_regs.h" - -#define ISS_PRINT_REGISTER(iss, name)\ - dev_dbg(iss->dev, "###ISS " #name "=0x%08x\n", \ - iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_##name)) - -static void iss_print_status(struct iss_device *iss) -{ - dev_dbg(iss->dev, "-------------ISS HL Register dump-------------\n"); - - ISS_PRINT_REGISTER(iss, HL_REVISION); - ISS_PRINT_REGISTER(iss, HL_SYSCONFIG); - ISS_PRINT_REGISTER(iss, HL_IRQSTATUS(5)); - ISS_PRINT_REGISTER(iss, HL_IRQENABLE_SET(5)); - ISS_PRINT_REGISTER(iss, HL_IRQENABLE_CLR(5)); - ISS_PRINT_REGISTER(iss, CTRL); - ISS_PRINT_REGISTER(iss, CLKCTRL); - ISS_PRINT_REGISTER(iss, CLKSTAT); - - dev_dbg(iss->dev, "-----------------------------------------------\n"); -} - -/* - * omap4iss_flush - Post pending L3 bus writes by doing a register readback - * @iss: OMAP4 ISS device - * - * In order to force posting of pending writes, we need to write and - * readback the same register, in this case the revision register. - * - * See this link for reference: - * https://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html - */ -static void omap4iss_flush(struct iss_device *iss) -{ - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION, 0); - iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION); -} - -/* - * iss_isp_enable_interrupts - Enable ISS ISP interrupts. - * @iss: OMAP4 ISS device - */ -static void omap4iss_isp_enable_interrupts(struct iss_device *iss) -{ - static const u32 isp_irq = ISP5_IRQ_OCP_ERR | - ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | - ISP5_IRQ_RSZ_FIFO_OVF | - ISP5_IRQ_RSZ_INT_DMA | - ISP5_IRQ_ISIF_INT(0); - - /* Enable ISP interrupts */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), isp_irq); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_SET(0), - isp_irq); -} - -/* - * iss_isp_disable_interrupts - Disable ISS interrupts. - * @iss: OMAP4 ISS device - */ -static void omap4iss_isp_disable_interrupts(struct iss_device *iss) -{ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_CLR(0), ~0); -} - -/* - * iss_enable_interrupts - Enable ISS interrupts. - * @iss: OMAP4 ISS device - */ -static void iss_enable_interrupts(struct iss_device *iss) -{ - static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB - | ISS_HL_IRQ_ISP(0); - - /* Enable HL interrupts */ - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), hl_irq); - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_SET(5), hl_irq); - - if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1]) - omap4iss_isp_enable_interrupts(iss); -} - -/* - * iss_disable_interrupts - Disable ISS interrupts. - * @iss: OMAP4 ISS device - */ -static void iss_disable_interrupts(struct iss_device *iss) -{ - if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1]) - omap4iss_isp_disable_interrupts(iss); - - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_CLR(5), ~0); -} - -int omap4iss_get_external_info(struct iss_pipeline *pipe, - struct media_link *link) -{ - struct iss_device *iss = - container_of(pipe, struct iss_video, pipe)->iss; - struct v4l2_subdev_format fmt; - struct v4l2_ctrl *ctrl; - int ret; - - if (!pipe->external) - return 0; - - if (pipe->external_rate) - return 0; - - memset(&fmt, 0, sizeof(fmt)); - - fmt.pad = link->source->index; - fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(link->sink->entity), - pad, get_fmt, NULL, &fmt); - if (ret < 0) - return -EPIPE; - - pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp; - - ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler, - V4L2_CID_PIXEL_RATE); - if (!ctrl) { - dev_warn(iss->dev, "no pixel rate control in subdev %s\n", - pipe->external->name); - return -EPIPE; - } - - pipe->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl); - - return 0; -} - -/* - * Configure the bridge. Valid inputs are - * - * IPIPEIF_INPUT_CSI2A: CSI2a receiver - * IPIPEIF_INPUT_CSI2B: CSI2b receiver - * - * The bridge and lane shifter are configured according to the selected input - * and the ISP platform data. - */ -void omap4iss_configure_bridge(struct iss_device *iss, - enum ipipeif_input_entity input) -{ - u32 issctrl_val; - u32 isp5ctrl_val; - - issctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL); - issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK; - issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK; - - isp5ctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL); - - switch (input) { - case IPIPEIF_INPUT_CSI2A: - issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A; - break; - - case IPIPEIF_INPUT_CSI2B: - issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B; - break; - - default: - return; - } - - issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING; - - isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT | ISP5_CTRL_PSYNC_CLK_SEL | - ISP5_CTRL_SYNC_ENABLE; - - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL, issctrl_val); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, isp5ctrl_val); -} - -#ifdef ISS_ISR_DEBUG -static void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) -{ - static const char * const name[] = { - "ISP_0", - "ISP_1", - "ISP_2", - "ISP_3", - "CSIA", - "CSIB", - "CCP2_0", - "CCP2_1", - "CCP2_2", - "CCP2_3", - "CBUFF", - "BTE", - "SIMCOP_0", - "SIMCOP_1", - "SIMCOP_2", - "SIMCOP_3", - "CCP2_8", - "HS_VS", - "18", - "19", - "20", - "21", - "22", - "23", - "24", - "25", - "26", - "27", - "28", - "29", - "30", - "31", - }; - unsigned int i; - - dev_dbg(iss->dev, "ISS IRQ: "); - - for (i = 0; i < ARRAY_SIZE(name); i++) { - if ((1 << i) & irqstatus) - pr_cont("%s ", name[i]); - } - pr_cont("\n"); -} - -static void iss_isp_isr_dbg(struct iss_device *iss, u32 irqstatus) -{ - static const char * const name[] = { - "ISIF_0", - "ISIF_1", - "ISIF_2", - "ISIF_3", - "IPIPEREQ", - "IPIPELAST_PIX", - "IPIPEDMA", - "IPIPEBSC", - "IPIPEHST", - "IPIPEIF", - "AEW", - "AF", - "H3A", - "RSZ_REG", - "RSZ_LAST_PIX", - "RSZ_DMA", - "RSZ_CYC_RZA", - "RSZ_CYC_RZB", - "RSZ_FIFO_OVF", - "RSZ_FIFO_IN_BLK_ERR", - "20", - "21", - "RSZ_EOF0", - "RSZ_EOF1", - "H3A_EOF", - "IPIPE_EOF", - "26", - "IPIPE_DPC_INI", - "IPIPE_DPC_RNEW0", - "IPIPE_DPC_RNEW1", - "30", - "OCP_ERR", - }; - unsigned int i; - - dev_dbg(iss->dev, "ISP IRQ: "); - - for (i = 0; i < ARRAY_SIZE(name); i++) { - if ((1 << i) & irqstatus) - pr_cont("%s ", name[i]); - } - pr_cont("\n"); -} -#endif - -/* - * iss_isr - Interrupt Service Routine for ISS module. - * @irq: Not used currently. - * @_iss: Pointer to the OMAP4 ISS device - * - * Handles the corresponding callback if plugged in. - * - * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the - * IRQ wasn't handled. - */ -static irqreturn_t iss_isr(int irq, void *_iss) -{ - static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF_IRQ | - ISP5_IRQ_ISIF_INT(0); - static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | - ISP5_IRQ_RSZ_FIFO_OVF | - ISP5_IRQ_RSZ_INT_DMA; - struct iss_device *iss = _iss; - u32 irqstatus; - - irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5)); - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), irqstatus); - - if (irqstatus & ISS_HL_IRQ_CSIA) - omap4iss_csi2_isr(&iss->csi2a); - - if (irqstatus & ISS_HL_IRQ_CSIB) - omap4iss_csi2_isr(&iss->csi2b); - - if (irqstatus & ISS_HL_IRQ_ISP(0)) { - u32 isp_irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, - ISP5_IRQSTATUS(0)); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), - isp_irqstatus); - - if (isp_irqstatus & ISP5_IRQ_OCP_ERR) - dev_dbg(iss->dev, "ISP5 OCP Error!\n"); - - if (isp_irqstatus & ipipeif_events) { - omap4iss_ipipeif_isr(&iss->ipipeif, - isp_irqstatus & ipipeif_events); - } - - if (isp_irqstatus & resizer_events) - omap4iss_resizer_isr(&iss->resizer, - isp_irqstatus & resizer_events); - -#ifdef ISS_ISR_DEBUG - iss_isp_isr_dbg(iss, isp_irqstatus); -#endif - } - - omap4iss_flush(iss); - -#ifdef ISS_ISR_DEBUG - iss_isr_dbg(iss, irqstatus); -#endif - - return IRQ_HANDLED; -} - -static const struct media_device_ops iss_media_ops = { - .link_notify = v4l2_pipeline_link_notify, -}; - -/* ----------------------------------------------------------------------------- - * Pipeline stream management - */ - -/* - * iss_pipeline_disable - Disable streaming on a pipeline - * @pipe: ISS pipeline - * @until: entity at which to stop pipeline walk - * - * Walk the entities chain starting at the pipeline output video node and stop - * all modules in the chain. Wait synchronously for the modules to be stopped if - * necessary. - * - * If the until argument isn't NULL, stop the pipeline walk when reaching the - * until entity. This is used to disable a partially started pipeline due to a - * subdev start error. - */ -static int iss_pipeline_disable(struct iss_pipeline *pipe, - struct media_entity *until) -{ - struct iss_device *iss = pipe->output->iss; - struct media_entity *entity; - struct media_pad *pad; - struct v4l2_subdev *subdev; - int failure = 0; - int ret; - - entity = &pipe->output->video.entity; - while (1) { - pad = &entity->pads[0]; - if (!(pad->flags & MEDIA_PAD_FL_SINK)) - break; - - pad = media_pad_remote_pad_first(pad); - if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) - break; - - entity = pad->entity; - if (entity == until) - break; - - subdev = media_entity_to_v4l2_subdev(entity); - ret = v4l2_subdev_call(subdev, video, s_stream, 0); - if (ret < 0) { - dev_warn(iss->dev, "%s: module stop timeout.\n", - subdev->name); - /* If the entity failed to stopped, assume it has - * crashed. Mark it as such, the ISS will be reset when - * applications will release it. - */ - media_entity_enum_set(&iss->crashed, &subdev->entity); - failure = -ETIMEDOUT; - } - } - - return failure; -} - -/* - * iss_pipeline_enable - Enable streaming on a pipeline - * @pipe: ISS pipeline - * @mode: Stream mode (single shot or continuous) - * - * Walk the entities chain starting at the pipeline output video node and start - * all modules in the chain in the given mode. - * - * Return 0 if successful, or the return value of the failed video::s_stream - * operation otherwise. - */ -static int iss_pipeline_enable(struct iss_pipeline *pipe, - enum iss_pipeline_stream_state mode) -{ - struct iss_device *iss = pipe->output->iss; - struct media_entity *entity; - struct media_pad *pad; - struct v4l2_subdev *subdev; - unsigned long flags; - int ret; - - /* If one of the entities in the pipeline has crashed it will not work - * properly. Refuse to start streaming in that case. This check must be - * performed before the loop below to avoid starting entities if the - * pipeline won't start anyway (those entities would then likely fail to - * stop, making the problem worse). - */ - if (media_entity_enum_intersects(&pipe->ent_enum, &iss->crashed)) - return -EIO; - - spin_lock_irqsave(&pipe->lock, flags); - pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT); - spin_unlock_irqrestore(&pipe->lock, flags); - - pipe->do_propagation = false; - - mutex_lock(&iss->media_dev.graph_mutex); - - entity = &pipe->output->video.entity; - while (1) { - pad = &entity->pads[0]; - if (!(pad->flags & MEDIA_PAD_FL_SINK)) - break; - - pad = media_pad_remote_pad_first(pad); - if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) - break; - - entity = pad->entity; - subdev = media_entity_to_v4l2_subdev(entity); - - ret = v4l2_subdev_call(subdev, video, s_stream, mode); - if (ret < 0 && ret != -ENOIOCTLCMD) { - iss_pipeline_disable(pipe, entity); - mutex_unlock(&iss->media_dev.graph_mutex); - return ret; - } - - if (subdev == &iss->csi2a.subdev || - subdev == &iss->csi2b.subdev) - pipe->do_propagation = true; - } - - mutex_unlock(&iss->media_dev.graph_mutex); - iss_print_status(pipe->output->iss); - - return 0; -} - -/* - * omap4iss_pipeline_set_stream - Enable/disable streaming on a pipeline - * @pipe: ISS pipeline - * @state: Stream state (stopped, single shot or continuous) - * - * Set the pipeline to the given stream state. Pipelines can be started in - * single-shot or continuous mode. - * - * Return 0 if successful, or the return value of the failed video::s_stream - * operation otherwise. The pipeline state is not updated when the operation - * fails, except when stopping the pipeline. - */ -int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, - enum iss_pipeline_stream_state state) -{ - int ret; - - if (state == ISS_PIPELINE_STREAM_STOPPED) - ret = iss_pipeline_disable(pipe, NULL); - else - ret = iss_pipeline_enable(pipe, state); - - if (ret == 0 || state == ISS_PIPELINE_STREAM_STOPPED) - pipe->stream_state = state; - - return ret; -} - -/* - * omap4iss_pipeline_cancel_stream - Cancel stream on a pipeline - * @pipe: ISS pipeline - * - * Cancelling a stream mark all buffers on all video nodes in the pipeline as - * erroneous and makes sure no new buffer can be queued. This function is called - * when a fatal error that prevents any further operation on the pipeline - * occurs. - */ -void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe) -{ - if (pipe->input) - omap4iss_video_cancel_stream(pipe->input); - if (pipe->output) - omap4iss_video_cancel_stream(pipe->output); -} - -/* - * iss_pipeline_is_last - Verify if entity has an enabled link to the output - * video node - * @me: ISS module's media entity - * - * Returns 1 if the entity has an enabled link to the output video node or 0 - * otherwise. It's true only while pipeline can have no more than one output - * node. - */ -static int iss_pipeline_is_last(struct media_entity *me) -{ - struct iss_pipeline *pipe; - struct media_pad *pad; - - pipe = to_iss_pipeline(me); - if (!pipe || pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED) - return 0; - pad = media_pad_remote_pad_first(&pipe->output->pad); - return pad->entity == me; -} - -static int iss_reset(struct iss_device *iss) -{ - unsigned int timeout; - - iss_reg_set(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG, - ISS_HL_SYSCONFIG_SOFTRESET); - - timeout = iss_poll_condition_timeout( - !(iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG) & - ISS_HL_SYSCONFIG_SOFTRESET), 1000, 10, 100); - if (timeout) { - dev_err(iss->dev, "ISS reset timeout\n"); - return -ETIMEDOUT; - } - - media_entity_enum_zero(&iss->crashed); - - return 0; -} - -static int iss_isp_reset(struct iss_device *iss) -{ - unsigned int timeout; - - /* Fist, ensure that the ISP is IDLE (no transactions happening) */ - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG, - ISP5_SYSCONFIG_STANDBYMODE_MASK, - ISP5_SYSCONFIG_STANDBYMODE_SMART); - - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, ISP5_CTRL_MSTANDBY); - - timeout = iss_poll_condition_timeout( - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL) & - ISP5_CTRL_MSTANDBY_WAIT, 1000000, 1000, 1500); - if (timeout) { - dev_err(iss->dev, "ISP5 standby timeout\n"); - return -ETIMEDOUT; - } - - /* Now finally, do the reset */ - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG, - ISP5_SYSCONFIG_SOFTRESET); - - timeout = iss_poll_condition_timeout( - !(iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG) & - ISP5_SYSCONFIG_SOFTRESET), 1000000, 1000, 1500); - if (timeout) { - dev_err(iss->dev, "ISP5 reset timeout\n"); - return -ETIMEDOUT; - } - - return 0; -} - -/* - * iss_module_sync_idle - Helper to sync module with its idle state - * @me: ISS submodule's media entity - * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization - * @stopping: flag which tells module wants to stop - * - * This function checks if ISS submodule needs to wait for next interrupt. If - * yes, makes the caller to sleep while waiting for such event. - */ -int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait, - atomic_t *stopping) -{ - struct iss_pipeline *pipe = to_iss_pipeline(me); - struct iss_video *video = pipe->output; - unsigned long flags; - - if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED || - (pipe->stream_state == ISS_PIPELINE_STREAM_SINGLESHOT && - !iss_pipeline_ready(pipe))) - return 0; - - /* - * atomic_set() doesn't include memory barrier on ARM platform for SMP - * scenario. We'll call it here to avoid race conditions. - */ - atomic_set(stopping, 1); - smp_wmb(); - - /* - * If module is the last one, it's writing to memory. In this case, - * it's necessary to check if the module is already paused due to - * DMA queue underrun or if it has to wait for next interrupt to be - * idle. - * If it isn't the last one, the function won't sleep but *stopping - * will still be set to warn next submodule caller's interrupt the - * module wants to be idle. - */ - if (!iss_pipeline_is_last(me)) - return 0; - - spin_lock_irqsave(&video->qlock, flags); - if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { - spin_unlock_irqrestore(&video->qlock, flags); - atomic_set(stopping, 0); - smp_wmb(); - return 0; - } - spin_unlock_irqrestore(&video->qlock, flags); - if (!wait_event_timeout(*wait, !atomic_read(stopping), - msecs_to_jiffies(1000))) { - atomic_set(stopping, 0); - smp_wmb(); - return -ETIMEDOUT; - } - - return 0; -} - -/* - * omap4iss_module_sync_is_stopped - Helper to verify if module was stopping - * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization - * @stopping: flag which tells module wants to stop - * - * This function checks if ISS submodule was stopping. In case of yes, it - * notices the caller by setting stopping to 0 and waking up the wait queue. - * Returns 1 if it was stopping or 0 otherwise. - */ -int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait, - atomic_t *stopping) -{ - if (atomic_cmpxchg(stopping, 1, 0)) { - wake_up(wait); - return 1; - } - - return 0; -} - -/* -------------------------------------------------------------------------- - * Clock management - */ - -#define ISS_CLKCTRL_MASK (ISS_CLKCTRL_CSI2_A |\ - ISS_CLKCTRL_CSI2_B |\ - ISS_CLKCTRL_ISP) - -static int __iss_subclk_update(struct iss_device *iss) -{ - u32 clk = 0; - int ret = 0, timeout = 1000; - - if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_A) - clk |= ISS_CLKCTRL_CSI2_A; - - if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_B) - clk |= ISS_CLKCTRL_CSI2_B; - - if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP) - clk |= ISS_CLKCTRL_ISP; - - iss_reg_update(iss, OMAP4_ISS_MEM_TOP, ISS_CLKCTRL, - ISS_CLKCTRL_MASK, clk); - - /* Wait for HW assertion */ - while (--timeout > 0) { - udelay(1); - if ((iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CLKSTAT) & - ISS_CLKCTRL_MASK) == clk) - break; - } - - if (!timeout) - ret = -EBUSY; - - return ret; -} - -int omap4iss_subclk_enable(struct iss_device *iss, - enum iss_subclk_resource res) -{ - iss->subclk_resources |= res; - - return __iss_subclk_update(iss); -} - -int omap4iss_subclk_disable(struct iss_device *iss, - enum iss_subclk_resource res) -{ - iss->subclk_resources &= ~res; - - return __iss_subclk_update(iss); -} - -#define ISS_ISP5_CLKCTRL_MASK (ISP5_CTRL_BL_CLK_ENABLE |\ - ISP5_CTRL_ISIF_CLK_ENABLE |\ - ISP5_CTRL_H3A_CLK_ENABLE |\ - ISP5_CTRL_RSZ_CLK_ENABLE |\ - ISP5_CTRL_IPIPE_CLK_ENABLE |\ - ISP5_CTRL_IPIPEIF_CLK_ENABLE) - -static void __iss_isp_subclk_update(struct iss_device *iss) -{ - u32 clk = 0; - - if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_ISIF) - clk |= ISP5_CTRL_ISIF_CLK_ENABLE; - - if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_H3A) - clk |= ISP5_CTRL_H3A_CLK_ENABLE; - - if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_RSZ) - clk |= ISP5_CTRL_RSZ_CLK_ENABLE; - - if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPE) - clk |= ISP5_CTRL_IPIPE_CLK_ENABLE; - - if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPEIF) - clk |= ISP5_CTRL_IPIPEIF_CLK_ENABLE; - - if (clk) - clk |= ISP5_CTRL_BL_CLK_ENABLE; - - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, - ISS_ISP5_CLKCTRL_MASK, clk); -} - -void omap4iss_isp_subclk_enable(struct iss_device *iss, - enum iss_isp_subclk_resource res) -{ - iss->isp_subclk_resources |= res; - - __iss_isp_subclk_update(iss); -} - -void omap4iss_isp_subclk_disable(struct iss_device *iss, - enum iss_isp_subclk_resource res) -{ - iss->isp_subclk_resources &= ~res; - - __iss_isp_subclk_update(iss); -} - -/* - * iss_enable_clocks - Enable ISS clocks - * @iss: OMAP4 ISS device - * - * Return 0 if successful, or clk_enable return value if any of tthem fails. - */ -static int iss_enable_clocks(struct iss_device *iss) -{ - int ret; - - ret = clk_enable(iss->iss_fck); - if (ret) { - dev_err(iss->dev, "clk_enable iss_fck failed\n"); - return ret; - } - - ret = clk_enable(iss->iss_ctrlclk); - if (ret) { - dev_err(iss->dev, "clk_enable iss_ctrlclk failed\n"); - clk_disable(iss->iss_fck); - return ret; - } - - return 0; -} - -/* - * iss_disable_clocks - Disable ISS clocks - * @iss: OMAP4 ISS device - */ -static void iss_disable_clocks(struct iss_device *iss) -{ - clk_disable(iss->iss_ctrlclk); - clk_disable(iss->iss_fck); -} - -static int iss_get_clocks(struct iss_device *iss) -{ - iss->iss_fck = devm_clk_get(iss->dev, "iss_fck"); - if (IS_ERR(iss->iss_fck)) { - dev_err(iss->dev, "Unable to get iss_fck clock info\n"); - return PTR_ERR(iss->iss_fck); - } - - iss->iss_ctrlclk = devm_clk_get(iss->dev, "iss_ctrlclk"); - if (IS_ERR(iss->iss_ctrlclk)) { - dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n"); - return PTR_ERR(iss->iss_ctrlclk); - } - - return 0; -} - -/* - * omap4iss_get - Acquire the ISS resource. - * - * Initializes the clocks for the first acquire. - * - * Increment the reference count on the ISS. If the first reference is taken, - * enable clocks and power-up all submodules. - * - * Return a pointer to the ISS device structure, or NULL if an error occurred. - */ -struct iss_device *omap4iss_get(struct iss_device *iss) -{ - struct iss_device *__iss = iss; - - if (!iss) - return NULL; - - mutex_lock(&iss->iss_mutex); - if (iss->ref_count > 0) - goto out; - - if (iss_enable_clocks(iss) < 0) { - __iss = NULL; - goto out; - } - - iss_enable_interrupts(iss); - -out: - if (__iss) - iss->ref_count++; - mutex_unlock(&iss->iss_mutex); - - return __iss; -} - -/* - * omap4iss_put - Release the ISS - * - * Decrement the reference count on the ISS. If the last reference is released, - * power-down all submodules, disable clocks and free temporary buffers. - */ -void omap4iss_put(struct iss_device *iss) -{ - if (!iss) - return; - - mutex_lock(&iss->iss_mutex); - WARN_ON(iss->ref_count == 0); - if (--iss->ref_count == 0) { - iss_disable_interrupts(iss); - /* Reset the ISS if an entity has failed to stop. This is the - * only way to recover from such conditions, although it would - * be worth investigating whether resetting the ISP only can't - * fix the problem in some cases. - */ - if (!media_entity_enum_empty(&iss->crashed)) - iss_reset(iss); - iss_disable_clocks(iss); - } - mutex_unlock(&iss->iss_mutex); -} - -static int iss_map_mem_resource(struct platform_device *pdev, - struct iss_device *iss, - enum iss_mem_resources res) -{ - iss->regs[res] = devm_platform_ioremap_resource(pdev, res); - - return PTR_ERR_OR_ZERO(iss->regs[res]); -} - -static void iss_unregister_entities(struct iss_device *iss) -{ - omap4iss_resizer_unregister_entities(&iss->resizer); - omap4iss_ipipe_unregister_entities(&iss->ipipe); - omap4iss_ipipeif_unregister_entities(&iss->ipipeif); - omap4iss_csi2_unregister_entities(&iss->csi2a); - omap4iss_csi2_unregister_entities(&iss->csi2b); - - v4l2_device_unregister(&iss->v4l2_dev); - media_device_unregister(&iss->media_dev); -} - -/* - * iss_register_subdev_group - Register a group of subdevices - * @iss: OMAP4 ISS device - * @board_info: I2C subdevs board information array - * - * Register all I2C subdevices in the board_info array. The array must be - * terminated by a NULL entry, and the first entry must be the sensor. - * - * Return a pointer to the sensor media entity if it has been successfully - * registered, or NULL otherwise. - */ -static struct v4l2_subdev * -iss_register_subdev_group(struct iss_device *iss, - struct iss_subdev_i2c_board_info *board_info) -{ - struct v4l2_subdev *sensor = NULL; - unsigned int first; - - if (!board_info->board_info) - return NULL; - - for (first = 1; board_info->board_info; ++board_info, first = 0) { - struct v4l2_subdev *subdev; - struct i2c_adapter *adapter; - - adapter = i2c_get_adapter(board_info->i2c_adapter_id); - if (!adapter) { - dev_err(iss->dev, - "%s: Unable to get I2C adapter %d for device %s\n", - __func__, board_info->i2c_adapter_id, - board_info->board_info->type); - continue; - } - - subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter, - board_info->board_info, NULL); - if (!subdev) { - dev_err(iss->dev, "Unable to register subdev %s\n", - board_info->board_info->type); - continue; - } - - if (first) - sensor = subdev; - } - - return sensor; -} - -static int iss_register_entities(struct iss_device *iss) -{ - struct iss_platform_data *pdata = iss->pdata; - struct iss_v4l2_subdevs_group *subdevs; - int ret; - - iss->media_dev.dev = iss->dev; - strscpy(iss->media_dev.model, "TI OMAP4 ISS", - sizeof(iss->media_dev.model)); - iss->media_dev.hw_revision = iss->revision; - iss->media_dev.ops = &iss_media_ops; - ret = media_device_register(&iss->media_dev); - if (ret < 0) { - dev_err(iss->dev, "Media device registration failed (%d)\n", - ret); - return ret; - } - - iss->v4l2_dev.mdev = &iss->media_dev; - ret = v4l2_device_register(iss->dev, &iss->v4l2_dev); - if (ret < 0) { - dev_err(iss->dev, "V4L2 device registration failed (%d)\n", - ret); - goto done; - } - - /* Register internal entities */ - ret = omap4iss_csi2_register_entities(&iss->csi2a, &iss->v4l2_dev); - if (ret < 0) - goto done; - - ret = omap4iss_csi2_register_entities(&iss->csi2b, &iss->v4l2_dev); - if (ret < 0) - goto done; - - ret = omap4iss_ipipeif_register_entities(&iss->ipipeif, &iss->v4l2_dev); - if (ret < 0) - goto done; - - ret = omap4iss_ipipe_register_entities(&iss->ipipe, &iss->v4l2_dev); - if (ret < 0) - goto done; - - ret = omap4iss_resizer_register_entities(&iss->resizer, &iss->v4l2_dev); - if (ret < 0) - goto done; - - /* Register external entities */ - for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) { - struct v4l2_subdev *sensor; - struct media_entity *input; - unsigned int flags; - unsigned int pad; - - sensor = iss_register_subdev_group(iss, subdevs->subdevs); - if (!sensor) - continue; - - sensor->host_priv = subdevs; - - /* Connect the sensor to the correct interface module. - * CSI2a receiver through CSIPHY1, or - * CSI2b receiver through CSIPHY2 - */ - switch (subdevs->interface) { - case ISS_INTERFACE_CSI2A_PHY1: - input = &iss->csi2a.subdev.entity; - pad = CSI2_PAD_SINK; - flags = MEDIA_LNK_FL_IMMUTABLE - | MEDIA_LNK_FL_ENABLED; - break; - - case ISS_INTERFACE_CSI2B_PHY2: - input = &iss->csi2b.subdev.entity; - pad = CSI2_PAD_SINK; - flags = MEDIA_LNK_FL_IMMUTABLE - | MEDIA_LNK_FL_ENABLED; - break; - - default: - dev_err(iss->dev, "invalid interface type %u\n", - subdevs->interface); - ret = -EINVAL; - goto done; - } - - ret = media_create_pad_link(&sensor->entity, 0, input, pad, - flags); - if (ret < 0) - goto done; - } - - ret = v4l2_device_register_subdev_nodes(&iss->v4l2_dev); - -done: - if (ret < 0) - iss_unregister_entities(iss); - - return ret; -} - -/* - * iss_create_links() - Pads links creation for the subdevices - * @iss : Pointer to ISS device - * - * return negative error code or zero on success - */ -static int iss_create_links(struct iss_device *iss) -{ - int ret; - - ret = omap4iss_csi2_create_links(iss); - if (ret < 0) { - dev_err(iss->dev, "CSI2 pads links creation failed\n"); - return ret; - } - - ret = omap4iss_ipipeif_create_links(iss); - if (ret < 0) { - dev_err(iss->dev, "ISP IPIPEIF pads links creation failed\n"); - return ret; - } - - ret = omap4iss_resizer_create_links(iss); - if (ret < 0) { - dev_err(iss->dev, "ISP RESIZER pads links creation failed\n"); - return ret; - } - - /* Connect the submodules. */ - ret = media_create_pad_link( - &iss->csi2a.subdev.entity, CSI2_PAD_SOURCE, - &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); - if (ret < 0) - return ret; - - ret = media_create_pad_link( - &iss->csi2b.subdev.entity, CSI2_PAD_SOURCE, - &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); - if (ret < 0) - return ret; - - ret = media_create_pad_link( - &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, - &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); - if (ret < 0) - return ret; - - ret = media_create_pad_link( - &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, - &iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0); - if (ret < 0) - return ret; - - ret = media_create_pad_link( - &iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP, - &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); - if (ret < 0) - return ret; - - return 0; -}; - -static void iss_cleanup_modules(struct iss_device *iss) -{ - omap4iss_csi2_cleanup(iss); - omap4iss_ipipeif_cleanup(iss); - omap4iss_ipipe_cleanup(iss); - omap4iss_resizer_cleanup(iss); -} - -static int iss_initialize_modules(struct iss_device *iss) -{ - int ret; - - ret = omap4iss_csiphy_init(iss); - if (ret < 0) { - dev_err(iss->dev, "CSI PHY initialization failed\n"); - goto error_csiphy; - } - - ret = omap4iss_csi2_init(iss); - if (ret < 0) { - dev_err(iss->dev, "CSI2 initialization failed\n"); - goto error_csi2; - } - - ret = omap4iss_ipipeif_init(iss); - if (ret < 0) { - dev_err(iss->dev, "ISP IPIPEIF initialization failed\n"); - goto error_ipipeif; - } - - ret = omap4iss_ipipe_init(iss); - if (ret < 0) { - dev_err(iss->dev, "ISP IPIPE initialization failed\n"); - goto error_ipipe; - } - - ret = omap4iss_resizer_init(iss); - if (ret < 0) { - dev_err(iss->dev, "ISP RESIZER initialization failed\n"); - goto error_resizer; - } - - return 0; - -error_resizer: - omap4iss_ipipe_cleanup(iss); -error_ipipe: - omap4iss_ipipeif_cleanup(iss); -error_ipipeif: - omap4iss_csi2_cleanup(iss); -error_csi2: -error_csiphy: - return ret; -} - -static int iss_probe(struct platform_device *pdev) -{ - struct iss_platform_data *pdata = pdev->dev.platform_data; - struct iss_device *iss; - unsigned int i; - int ret; - - if (!pdata) - return -EINVAL; - - iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL); - if (!iss) - return -ENOMEM; - - mutex_init(&iss->iss_mutex); - - iss->dev = &pdev->dev; - iss->pdata = pdata; - - iss->raw_dmamask = DMA_BIT_MASK(32); - iss->dev->dma_mask = &iss->raw_dmamask; - iss->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - platform_set_drvdata(pdev, iss); - - /* - * TODO: When implementing DT support switch to syscon regmap lookup by - * phandle. - */ - iss->syscon = syscon_regmap_lookup_by_compatible("syscon"); - if (IS_ERR(iss->syscon)) { - ret = PTR_ERR(iss->syscon); - goto error; - } - - /* Clocks */ - ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP); - if (ret < 0) - goto error; - - ret = iss_get_clocks(iss); - if (ret < 0) - goto error; - - if (!omap4iss_get(iss)) { - ret = -EINVAL; - goto error; - } - - ret = iss_reset(iss); - if (ret < 0) - goto error_iss; - - iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION); - dev_info(iss->dev, "Revision %08x found\n", iss->revision); - - for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) { - ret = iss_map_mem_resource(pdev, iss, i); - if (ret) - goto error_iss; - } - - /* Configure BTE BW_LIMITER field to max recommended value (1 GB) */ - iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL, - BTE_CTRL_BW_LIMITER_MASK, - 18 << BTE_CTRL_BW_LIMITER_SHIFT); - - /* Perform ISP reset */ - ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP); - if (ret < 0) - goto error_iss; - - ret = iss_isp_reset(iss); - if (ret < 0) - goto error_iss; - - dev_info(iss->dev, "ISP Revision %08x found\n", - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION)); - - /* Interrupt */ - ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - ret = -ENODEV; - goto error_iss; - } - iss->irq_num = ret; - - if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED, - "OMAP4 ISS", iss)) { - dev_err(iss->dev, "Unable to request IRQ\n"); - ret = -EINVAL; - goto error_iss; - } - - /* Entities */ - ret = iss_initialize_modules(iss); - if (ret < 0) - goto error_iss; - - ret = iss_register_entities(iss); - if (ret < 0) - goto error_modules; - - ret = media_entity_enum_init(&iss->crashed, &iss->media_dev); - if (ret) - goto error_entities; - - ret = iss_create_links(iss); - if (ret < 0) - goto error_entities; - - omap4iss_put(iss); - - return 0; - -error_entities: - iss_unregister_entities(iss); - media_entity_enum_cleanup(&iss->crashed); -error_modules: - iss_cleanup_modules(iss); -error_iss: - omap4iss_put(iss); -error: - mutex_destroy(&iss->iss_mutex); - - return ret; -} - -static void iss_remove(struct platform_device *pdev) -{ - struct iss_device *iss = platform_get_drvdata(pdev); - - iss_unregister_entities(iss); - media_entity_enum_cleanup(&iss->crashed); - iss_cleanup_modules(iss); -} - -static const struct platform_device_id omap4iss_id_table[] = { - { "omap4iss", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(platform, omap4iss_id_table); - -static struct platform_driver iss_driver = { - .probe = iss_probe, - .remove_new = iss_remove, - .id_table = omap4iss_id_table, - .driver = { - .name = "omap4iss", - }, -}; - -module_platform_driver(iss_driver); - -MODULE_DESCRIPTION("TI OMAP4 ISS driver"); -MODULE_AUTHOR("Sergio Aguirre "); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h deleted file mode 100644 index 3f587e000729..000000000000 --- a/drivers/staging/media/omap4iss/iss.h +++ /dev/null @@ -1,247 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * TI OMAP4 ISS V4L2 Driver - * - * Copyright (C) 2012 Texas Instruments. - * - * Author: Sergio Aguirre - */ - -#ifndef _OMAP4_ISS_H_ -#define _OMAP4_ISS_H_ - -#include -#include - -#include -#include -#include -#include - -#include - -#include "iss_regs.h" -#include "iss_csiphy.h" -#include "iss_csi2.h" -#include "iss_ipipeif.h" -#include "iss_ipipe.h" -#include "iss_resizer.h" - -struct regmap; - -#define to_iss_device(ptr_module) \ - container_of(ptr_module, struct iss_device, ptr_module) -#define to_device(ptr_module) \ - (to_iss_device(ptr_module)->dev) - -enum iss_mem_resources { - OMAP4_ISS_MEM_TOP, - OMAP4_ISS_MEM_CSI2_A_REGS1, - OMAP4_ISS_MEM_CAMERARX_CORE1, - OMAP4_ISS_MEM_CSI2_B_REGS1, - OMAP4_ISS_MEM_CAMERARX_CORE2, - OMAP4_ISS_MEM_BTE, - OMAP4_ISS_MEM_ISP_SYS1, - OMAP4_ISS_MEM_ISP_RESIZER, - OMAP4_ISS_MEM_ISP_IPIPE, - OMAP4_ISS_MEM_ISP_ISIF, - OMAP4_ISS_MEM_ISP_IPIPEIF, - OMAP4_ISS_MEM_LAST, -}; - -enum iss_subclk_resource { - OMAP4_ISS_SUBCLK_SIMCOP = (1 << 0), - OMAP4_ISS_SUBCLK_ISP = (1 << 1), - OMAP4_ISS_SUBCLK_CSI2_A = (1 << 2), - OMAP4_ISS_SUBCLK_CSI2_B = (1 << 3), - OMAP4_ISS_SUBCLK_CCP2 = (1 << 4), -}; - -enum iss_isp_subclk_resource { - OMAP4_ISS_ISP_SUBCLK_BL = (1 << 0), - OMAP4_ISS_ISP_SUBCLK_ISIF = (1 << 1), - OMAP4_ISS_ISP_SUBCLK_H3A = (1 << 2), - OMAP4_ISS_ISP_SUBCLK_RSZ = (1 << 3), - OMAP4_ISS_ISP_SUBCLK_IPIPE = (1 << 4), - OMAP4_ISS_ISP_SUBCLK_IPIPEIF = (1 << 5), -}; - -/* - * struct iss_reg - Structure for ISS register values. - * @reg: 32-bit Register address. - * @val: 32-bit Register value. - */ -struct iss_reg { - enum iss_mem_resources mmio_range; - u32 reg; - u32 val; -}; - -/* - * struct iss_device - ISS device structure. - * @syscon: Regmap for the syscon register space - * @crashed: Crashed entities - */ -struct iss_device { - struct v4l2_device v4l2_dev; - struct media_device media_dev; - struct device *dev; - u32 revision; - - /* platform HW resources */ - struct iss_platform_data *pdata; - unsigned int irq_num; - - struct resource *res[OMAP4_ISS_MEM_LAST]; - void __iomem *regs[OMAP4_ISS_MEM_LAST]; - struct regmap *syscon; - - u64 raw_dmamask; - - struct mutex iss_mutex; /* For handling ref_count field */ - struct media_entity_enum crashed; - int has_context; - int ref_count; - - struct clk *iss_fck; - struct clk *iss_ctrlclk; - - /* ISS modules */ - struct iss_csi2_device csi2a; - struct iss_csi2_device csi2b; - struct iss_csiphy csiphy1; - struct iss_csiphy csiphy2; - struct iss_ipipeif_device ipipeif; - struct iss_ipipe_device ipipe; - struct iss_resizer_device resizer; - - unsigned int subclk_resources; - unsigned int isp_subclk_resources; -}; - -int omap4iss_get_external_info(struct iss_pipeline *pipe, - struct media_link *link); - -int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait, - atomic_t *stopping); - -int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait, - atomic_t *stopping); - -int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, - enum iss_pipeline_stream_state state); -void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe); - -void omap4iss_configure_bridge(struct iss_device *iss, - enum ipipeif_input_entity input); - -struct iss_device *omap4iss_get(struct iss_device *iss); -void omap4iss_put(struct iss_device *iss); -int omap4iss_subclk_enable(struct iss_device *iss, - enum iss_subclk_resource res); -int omap4iss_subclk_disable(struct iss_device *iss, - enum iss_subclk_resource res); -void omap4iss_isp_subclk_enable(struct iss_device *iss, - enum iss_isp_subclk_resource res); -void omap4iss_isp_subclk_disable(struct iss_device *iss, - enum iss_isp_subclk_resource res); - -int omap4iss_register_entities(struct platform_device *pdev, - struct v4l2_device *v4l2_dev); -void omap4iss_unregister_entities(struct platform_device *pdev); - -/* - * iss_reg_read - Read the value of an OMAP4 ISS register - * @iss: the ISS device - * @res: memory resource in which the register is located - * @offset: register offset in the memory resource - * - * Return the register value. - */ -static inline -u32 iss_reg_read(struct iss_device *iss, enum iss_mem_resources res, - u32 offset) -{ - return readl(iss->regs[res] + offset); -} - -/* - * iss_reg_write - Write a value to an OMAP4 ISS register - * @iss: the ISS device - * @res: memory resource in which the register is located - * @offset: register offset in the memory resource - * @value: value to be written - */ -static inline -void iss_reg_write(struct iss_device *iss, enum iss_mem_resources res, - u32 offset, u32 value) -{ - writel(value, iss->regs[res] + offset); -} - -/* - * iss_reg_clr - Clear bits in an OMAP4 ISS register - * @iss: the ISS device - * @res: memory resource in which the register is located - * @offset: register offset in the memory resource - * @clr: bit mask to be cleared - */ -static inline -void iss_reg_clr(struct iss_device *iss, enum iss_mem_resources res, - u32 offset, u32 clr) -{ - u32 v = iss_reg_read(iss, res, offset); - - iss_reg_write(iss, res, offset, v & ~clr); -} - -/* - * iss_reg_set - Set bits in an OMAP4 ISS register - * @iss: the ISS device - * @res: memory resource in which the register is located - * @offset: register offset in the memory resource - * @set: bit mask to be set - */ -static inline -void iss_reg_set(struct iss_device *iss, enum iss_mem_resources res, - u32 offset, u32 set) -{ - u32 v = iss_reg_read(iss, res, offset); - - iss_reg_write(iss, res, offset, v | set); -} - -/* - * iss_reg_update - Clear and set bits in an OMAP4 ISS register - * @iss: the ISS device - * @res: memory resource in which the register is located - * @offset: register offset in the memory resource - * @clr: bit mask to be cleared - * @set: bit mask to be set - * - * Clear the clr mask first and then set the set mask. - */ -static inline -void iss_reg_update(struct iss_device *iss, enum iss_mem_resources res, - u32 offset, u32 clr, u32 set) -{ - u32 v = iss_reg_read(iss, res, offset); - - iss_reg_write(iss, res, offset, (v & ~clr) | set); -} - -#define iss_poll_condition_timeout(cond, timeout, min_ival, max_ival) \ -({ \ - unsigned long __timeout = jiffies + usecs_to_jiffies(timeout); \ - unsigned int __min_ival = (min_ival); \ - unsigned int __max_ival = (max_ival); \ - bool __cond; \ - while (!(__cond = (cond))) { \ - if (time_after(jiffies, __timeout)) \ - break; \ - usleep_range(__min_ival, __max_ival); \ - } \ - !__cond; \ -}) - -#endif /* _OMAP4_ISS_H_ */ diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c deleted file mode 100644 index 0e6c5bd81930..000000000000 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ /dev/null @@ -1,1379 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * TI OMAP4 ISS V4L2 Driver - CSI PHY module - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#include -#include -#include -#include - -#include "iss.h" -#include "iss_regs.h" -#include "iss_csi2.h" - -/* - * csi2_if_enable - Enable CSI2 Receiver interface. - * @enable: enable flag - * - */ -static void csi2_if_enable(struct iss_csi2_device *csi2, u8 enable) -{ - struct iss_csi2_ctrl_cfg *currctrl = &csi2->ctrl; - - iss_reg_update(csi2->iss, csi2->regs1, CSI2_CTRL, CSI2_CTRL_IF_EN, - enable ? CSI2_CTRL_IF_EN : 0); - - currctrl->if_enable = enable; -} - -/* - * csi2_recv_config - CSI2 receiver module configuration. - * @currctrl: iss_csi2_ctrl_cfg structure - * - */ -static void csi2_recv_config(struct iss_csi2_device *csi2, - struct iss_csi2_ctrl_cfg *currctrl) -{ - u32 reg = 0; - - if (currctrl->frame_mode) - reg |= CSI2_CTRL_FRAME; - else - reg &= ~CSI2_CTRL_FRAME; - - if (currctrl->vp_clk_enable) - reg |= CSI2_CTRL_VP_CLK_EN; - else - reg &= ~CSI2_CTRL_VP_CLK_EN; - - if (currctrl->vp_only_enable) - reg |= CSI2_CTRL_VP_ONLY_EN; - else - reg &= ~CSI2_CTRL_VP_ONLY_EN; - - reg &= ~CSI2_CTRL_VP_OUT_CTRL_MASK; - reg |= currctrl->vp_out_ctrl << CSI2_CTRL_VP_OUT_CTRL_SHIFT; - - if (currctrl->ecc_enable) - reg |= CSI2_CTRL_ECC_EN; - else - reg &= ~CSI2_CTRL_ECC_EN; - - /* - * Set MFlag assertion boundaries to: - * Low: 4/8 of FIFO size - * High: 6/8 of FIFO size - */ - reg &= ~(CSI2_CTRL_MFLAG_LEVH_MASK | CSI2_CTRL_MFLAG_LEVL_MASK); - reg |= (2 << CSI2_CTRL_MFLAG_LEVH_SHIFT) | - (4 << CSI2_CTRL_MFLAG_LEVL_SHIFT); - - /* Generation of 16x64-bit bursts (Recommended) */ - reg |= CSI2_CTRL_BURST_SIZE_EXPAND; - - /* Do Non-Posted writes (Recommended) */ - reg |= CSI2_CTRL_NON_POSTED_WRITE; - - /* - * Enforce Little endian for all formats, including: - * YUV4:2:2 8-bit and YUV4:2:0 Legacy - */ - reg |= CSI2_CTRL_ENDIANNESS; - - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTRL, reg); -} - -static const unsigned int csi2_input_fmts[] = { - MEDIA_BUS_FMT_SGRBG10_1X10, - MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, - MEDIA_BUS_FMT_SRGGB10_1X10, - MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, - MEDIA_BUS_FMT_SBGGR10_1X10, - MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, - MEDIA_BUS_FMT_SGBRG10_1X10, - MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, - MEDIA_BUS_FMT_SBGGR8_1X8, - MEDIA_BUS_FMT_SGBRG8_1X8, - MEDIA_BUS_FMT_SGRBG8_1X8, - MEDIA_BUS_FMT_SRGGB8_1X8, - MEDIA_BUS_FMT_UYVY8_1X16, - MEDIA_BUS_FMT_YUYV8_1X16, -}; - -/* To set the format on the CSI2 requires a mapping function that takes - * the following inputs: - * - 3 different formats (at this time) - * - 2 destinations (mem, vp+mem) (vp only handled separately) - * - 2 decompression options (on, off) - * Output should be CSI2 frame format code - * Array indices as follows: [format][dest][decompr] - * Not all combinations are valid. 0 means invalid. - */ -static const u16 __csi2_fmt_map[][2][2] = { - /* RAW10 formats */ - { - /* Output to memory */ - { - /* No DPCM decompression */ - CSI2_PIX_FMT_RAW10_EXP16, - /* DPCM decompression */ - 0, - }, - /* Output to both */ - { - /* No DPCM decompression */ - CSI2_PIX_FMT_RAW10_EXP16_VP, - /* DPCM decompression */ - 0, - }, - }, - /* RAW10 DPCM8 formats */ - { - /* Output to memory */ - { - /* No DPCM decompression */ - CSI2_USERDEF_8BIT_DATA1, - /* DPCM decompression */ - CSI2_USERDEF_8BIT_DATA1_DPCM10, - }, - /* Output to both */ - { - /* No DPCM decompression */ - CSI2_PIX_FMT_RAW8_VP, - /* DPCM decompression */ - CSI2_USERDEF_8BIT_DATA1_DPCM10_VP, - }, - }, - /* RAW8 formats */ - { - /* Output to memory */ - { - /* No DPCM decompression */ - CSI2_PIX_FMT_RAW8, - /* DPCM decompression */ - 0, - }, - /* Output to both */ - { - /* No DPCM decompression */ - CSI2_PIX_FMT_RAW8_VP, - /* DPCM decompression */ - 0, - }, - }, - /* YUV422 formats */ - { - /* Output to memory */ - { - /* No DPCM decompression */ - CSI2_PIX_FMT_YUV422_8BIT, - /* DPCM decompression */ - 0, - }, - /* Output to both */ - { - /* No DPCM decompression */ - CSI2_PIX_FMT_YUV422_8BIT_VP16, - /* DPCM decompression */ - 0, - }, - }, -}; - -/* - * csi2_ctx_map_format - Map CSI2 sink media bus format to CSI2 format ID - * @csi2: ISS CSI2 device - * - * Returns CSI2 physical format id - */ -static u16 csi2_ctx_map_format(struct iss_csi2_device *csi2) -{ - const struct v4l2_mbus_framefmt *fmt = &csi2->formats[CSI2_PAD_SINK]; - int fmtidx, destidx; - - switch (fmt->code) { - case MEDIA_BUS_FMT_SGRBG10_1X10: - case MEDIA_BUS_FMT_SRGGB10_1X10: - case MEDIA_BUS_FMT_SBGGR10_1X10: - case MEDIA_BUS_FMT_SGBRG10_1X10: - fmtidx = 0; - break; - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8: - case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8: - case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8: - fmtidx = 1; - break; - case MEDIA_BUS_FMT_SBGGR8_1X8: - case MEDIA_BUS_FMT_SGBRG8_1X8: - case MEDIA_BUS_FMT_SGRBG8_1X8: - case MEDIA_BUS_FMT_SRGGB8_1X8: - fmtidx = 2; - break; - case MEDIA_BUS_FMT_UYVY8_1X16: - case MEDIA_BUS_FMT_YUYV8_1X16: - fmtidx = 3; - break; - default: - WARN(1, "CSI2: pixel format %08x unsupported!\n", - fmt->code); - return 0; - } - - if (!(csi2->output & CSI2_OUTPUT_IPIPEIF) && - !(csi2->output & CSI2_OUTPUT_MEMORY)) { - /* Neither output enabled is a valid combination */ - return CSI2_PIX_FMT_OTHERS; - } - - /* If we need to skip frames at the beginning of the stream disable the - * video port to avoid sending the skipped frames to the IPIPEIF. - */ - destidx = csi2->frame_skip ? 0 : !!(csi2->output & CSI2_OUTPUT_IPIPEIF); - - return __csi2_fmt_map[fmtidx][destidx][csi2->dpcm_decompress]; -} - -/* - * csi2_set_outaddr - Set memory address to save output image - * @csi2: Pointer to ISS CSI2a device. - * @addr: 32-bit memory address aligned on 32 byte boundary. - * - * Sets the memory address where the output will be saved. - * - * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte - * boundary. - */ -static void csi2_set_outaddr(struct iss_csi2_device *csi2, u32 addr) -{ - struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[0]; - - ctx->ping_addr = addr; - ctx->pong_addr = addr; - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PING_ADDR(ctx->ctxnum), - ctx->ping_addr); - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PONG_ADDR(ctx->ctxnum), - ctx->pong_addr); -} - -/* - * is_usr_def_mapping - Checks whether USER_DEF_MAPPING should - * be enabled by CSI2. - * @format_id: mapped format id - * - */ -static inline int is_usr_def_mapping(u32 format_id) -{ - return (format_id & 0xf0) == 0x40 ? 1 : 0; -} - -/* - * csi2_ctx_enable - Enable specified CSI2 context - * @ctxnum: Context number, valid between 0 and 7 values. - * @enable: enable - * - */ -static void csi2_ctx_enable(struct iss_csi2_device *csi2, u8 ctxnum, u8 enable) -{ - struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum]; - u32 reg; - - reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctxnum)); - - if (enable) { - unsigned int skip = 0; - - if (csi2->frame_skip) - skip = csi2->frame_skip; - else if (csi2->output & CSI2_OUTPUT_MEMORY) - skip = 1; - - reg &= ~CSI2_CTX_CTRL1_COUNT_MASK; - reg |= CSI2_CTX_CTRL1_COUNT_UNLOCK - | (skip << CSI2_CTX_CTRL1_COUNT_SHIFT) - | CSI2_CTX_CTRL1_CTX_EN; - } else { - reg &= ~CSI2_CTX_CTRL1_CTX_EN; - } - - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctxnum), reg); - ctx->enabled = enable; -} - -/* - * csi2_ctx_config - CSI2 context configuration. - * @ctx: context configuration - * - */ -static void csi2_ctx_config(struct iss_csi2_device *csi2, - struct iss_csi2_ctx_cfg *ctx) -{ - u32 reg = 0; - - ctx->frame = 0; - - /* Set up CSI2_CTx_CTRL1 */ - if (ctx->eof_enabled) - reg = CSI2_CTX_CTRL1_EOF_EN; - - if (ctx->eol_enabled) - reg |= CSI2_CTX_CTRL1_EOL_EN; - - if (ctx->checksum_enabled) - reg |= CSI2_CTX_CTRL1_CS_EN; - - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctx->ctxnum), reg); - - /* Set up CSI2_CTx_CTRL2 */ - reg = ctx->virtual_id << CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT; - reg |= ctx->format_id << CSI2_CTX_CTRL2_FORMAT_SHIFT; - - if (ctx->dpcm_decompress && ctx->dpcm_predictor) - reg |= CSI2_CTX_CTRL2_DPCM_PRED; - - if (is_usr_def_mapping(ctx->format_id)) - reg |= 2 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT; - - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL2(ctx->ctxnum), reg); - - /* Set up CSI2_CTx_CTRL3 */ - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL3(ctx->ctxnum), - ctx->alpha << CSI2_CTX_CTRL3_ALPHA_SHIFT); - - /* Set up CSI2_CTx_DAT_OFST */ - iss_reg_update(csi2->iss, csi2->regs1, CSI2_CTX_DAT_OFST(ctx->ctxnum), - CSI2_CTX_DAT_OFST_MASK, ctx->data_offset); - - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PING_ADDR(ctx->ctxnum), - ctx->ping_addr); - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PONG_ADDR(ctx->ctxnum), - ctx->pong_addr); -} - -/* - * csi2_timing_config - CSI2 timing configuration. - * @timing: csi2_timing_cfg structure - */ -static void csi2_timing_config(struct iss_csi2_device *csi2, - struct iss_csi2_timing_cfg *timing) -{ - u32 reg; - - reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_TIMING); - - if (timing->force_rx_mode) - reg |= CSI2_TIMING_FORCE_RX_MODE_IO1; - else - reg &= ~CSI2_TIMING_FORCE_RX_MODE_IO1; - - if (timing->stop_state_16x) - reg |= CSI2_TIMING_STOP_STATE_X16_IO1; - else - reg &= ~CSI2_TIMING_STOP_STATE_X16_IO1; - - if (timing->stop_state_4x) - reg |= CSI2_TIMING_STOP_STATE_X4_IO1; - else - reg &= ~CSI2_TIMING_STOP_STATE_X4_IO1; - - reg &= ~CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK; - reg |= timing->stop_state_counter << - CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT; - - iss_reg_write(csi2->iss, csi2->regs1, CSI2_TIMING, reg); -} - -/* - * csi2_irq_ctx_set - Enables CSI2 Context IRQs. - * @enable: Enable/disable CSI2 Context interrupts - */ -static void csi2_irq_ctx_set(struct iss_csi2_device *csi2, int enable) -{ - const u32 mask = CSI2_CTX_IRQ_FE | CSI2_CTX_IRQ_FS; - int i; - - for (i = 0; i < 8; i++) { - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(i), - mask); - if (enable) - iss_reg_set(csi2->iss, csi2->regs1, - CSI2_CTX_IRQENABLE(i), mask); - else - iss_reg_clr(csi2->iss, csi2->regs1, - CSI2_CTX_IRQENABLE(i), mask); - } -} - -/* - * csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs. - * @enable: Enable/disable CSI2 ComplexIO #1 interrupts - */ -static void csi2_irq_complexio1_set(struct iss_csi2_device *csi2, int enable) -{ - u32 reg; - - reg = CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT | - CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER | - CSI2_COMPLEXIO_IRQ_STATEULPM5 | - CSI2_COMPLEXIO_IRQ_ERRCONTROL5 | - CSI2_COMPLEXIO_IRQ_ERRESC5 | - CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 | - CSI2_COMPLEXIO_IRQ_ERRSOTHS5 | - CSI2_COMPLEXIO_IRQ_STATEULPM4 | - CSI2_COMPLEXIO_IRQ_ERRCONTROL4 | - CSI2_COMPLEXIO_IRQ_ERRESC4 | - CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 | - CSI2_COMPLEXIO_IRQ_ERRSOTHS4 | - CSI2_COMPLEXIO_IRQ_STATEULPM3 | - CSI2_COMPLEXIO_IRQ_ERRCONTROL3 | - CSI2_COMPLEXIO_IRQ_ERRESC3 | - CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 | - CSI2_COMPLEXIO_IRQ_ERRSOTHS3 | - CSI2_COMPLEXIO_IRQ_STATEULPM2 | - CSI2_COMPLEXIO_IRQ_ERRCONTROL2 | - CSI2_COMPLEXIO_IRQ_ERRESC2 | - CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 | - CSI2_COMPLEXIO_IRQ_ERRSOTHS2 | - CSI2_COMPLEXIO_IRQ_STATEULPM1 | - CSI2_COMPLEXIO_IRQ_ERRCONTROL1 | - CSI2_COMPLEXIO_IRQ_ERRESC1 | - CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 | - CSI2_COMPLEXIO_IRQ_ERRSOTHS1; - iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQSTATUS, reg); - if (enable) - iss_reg_set(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQENABLE, - reg); - else - iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQENABLE, - 0); -} - -/* - * csi2_irq_status_set - Enables CSI2 Status IRQs. - * @enable: Enable/disable CSI2 Status interrupts - */ -static void csi2_irq_status_set(struct iss_csi2_device *csi2, int enable) -{ - u32 reg; - - reg = CSI2_IRQ_OCP_ERR | - CSI2_IRQ_SHORT_PACKET | - CSI2_IRQ_ECC_CORRECTION | - CSI2_IRQ_ECC_NO_CORRECTION | - CSI2_IRQ_COMPLEXIO_ERR | - CSI2_IRQ_FIFO_OVF | - CSI2_IRQ_CONTEXT0; - iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQSTATUS, reg); - if (enable) - iss_reg_set(csi2->iss, csi2->regs1, CSI2_IRQENABLE, reg); - else - iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQENABLE, 0); -} - -/* - * omap4iss_csi2_reset - Resets the CSI2 module. - * - * Must be called with the phy lock held. - * - * Returns 0 if successful, or -EBUSY if power command didn't respond. - */ -int omap4iss_csi2_reset(struct iss_csi2_device *csi2) -{ - unsigned int timeout; - - if (!csi2->available) - return -ENODEV; - - if (csi2->phy->phy_in_use) - return -EBUSY; - - iss_reg_set(csi2->iss, csi2->regs1, CSI2_SYSCONFIG, - CSI2_SYSCONFIG_SOFT_RESET); - - timeout = iss_poll_condition_timeout( - iss_reg_read(csi2->iss, csi2->regs1, CSI2_SYSSTATUS) & - CSI2_SYSSTATUS_RESET_DONE, 500, 100, 200); - if (timeout) { - dev_err(csi2->iss->dev, "CSI2: Soft reset timeout!\n"); - return -EBUSY; - } - - iss_reg_set(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_CFG, - CSI2_COMPLEXIO_CFG_RESET_CTRL); - - timeout = iss_poll_condition_timeout( - iss_reg_read(csi2->iss, csi2->phy->phy_regs, REGISTER1) & - REGISTER1_RESET_DONE_CTRLCLK, 10000, 100, 500); - if (timeout) { - dev_err(csi2->iss->dev, "CSI2: CSI2_96M_FCLK reset timeout!\n"); - return -EBUSY; - } - - iss_reg_update(csi2->iss, csi2->regs1, CSI2_SYSCONFIG, - CSI2_SYSCONFIG_MSTANDBY_MODE_MASK | - CSI2_SYSCONFIG_AUTO_IDLE, - CSI2_SYSCONFIG_MSTANDBY_MODE_NO); - - return 0; -} - -static int csi2_configure(struct iss_csi2_device *csi2) -{ - const struct iss_v4l2_subdevs_group *pdata; - struct iss_csi2_timing_cfg *timing = &csi2->timing[0]; - struct v4l2_subdev *sensor; - struct media_pad *pad; - - /* - * CSI2 fields that can be updated while the context has - * been enabled or the interface has been enabled are not - * updated dynamically currently. So we do not allow to - * reconfigure if either has been enabled - */ - if (csi2->contexts[0].enabled || csi2->ctrl.if_enable) - return -EBUSY; - - pad = media_pad_remote_pad_first(&csi2->pads[CSI2_PAD_SINK]); - sensor = media_entity_to_v4l2_subdev(pad->entity); - pdata = sensor->host_priv; - - csi2->frame_skip = 0; - v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip); - - csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div; - csi2->ctrl.frame_mode = ISS_CSI2_FRAME_IMMEDIATE; - csi2->ctrl.ecc_enable = pdata->bus.csi2.crc; - - timing->force_rx_mode = 1; - timing->stop_state_16x = 1; - timing->stop_state_4x = 1; - timing->stop_state_counter = 0x1ff; - - /* - * The CSI2 receiver can't do any format conversion except DPCM - * decompression, so every set_format call configures both pads - * and enables DPCM decompression as a special case: - */ - if (csi2->formats[CSI2_PAD_SINK].code != - csi2->formats[CSI2_PAD_SOURCE].code) - csi2->dpcm_decompress = true; - else - csi2->dpcm_decompress = false; - - csi2->contexts[0].format_id = csi2_ctx_map_format(csi2); - - if (csi2->video_out.bpl_padding == 0) - csi2->contexts[0].data_offset = 0; - else - csi2->contexts[0].data_offset = csi2->video_out.bpl_value; - - /* - * Enable end of frame and end of line signals generation for - * context 0. These signals are generated from CSI2 receiver to - * qualify the last pixel of a frame and the last pixel of a line. - * Without enabling the signals CSI2 receiver writes data to memory - * beyond buffer size and/or data line offset is not handled correctly. - */ - csi2->contexts[0].eof_enabled = 1; - csi2->contexts[0].eol_enabled = 1; - - csi2_irq_complexio1_set(csi2, 1); - csi2_irq_ctx_set(csi2, 1); - csi2_irq_status_set(csi2, 1); - - /* Set configuration (timings, format and links) */ - csi2_timing_config(csi2, timing); - csi2_recv_config(csi2, &csi2->ctrl); - csi2_ctx_config(csi2, &csi2->contexts[0]); - - return 0; -} - -/* - * csi2_print_status - Prints CSI2 debug information. - */ -#define CSI2_PRINT_REGISTER(iss, regs, name)\ - dev_dbg(iss->dev, "###CSI2 " #name "=0x%08x\n", \ - iss_reg_read(iss, regs, CSI2_##name)) - -static void csi2_print_status(struct iss_csi2_device *csi2) -{ - struct iss_device *iss = csi2->iss; - - if (!csi2->available) - return; - - dev_dbg(iss->dev, "-------------CSI2 Register dump-------------\n"); - - CSI2_PRINT_REGISTER(iss, csi2->regs1, SYSCONFIG); - CSI2_PRINT_REGISTER(iss, csi2->regs1, SYSSTATUS); - CSI2_PRINT_REGISTER(iss, csi2->regs1, IRQENABLE); - CSI2_PRINT_REGISTER(iss, csi2->regs1, IRQSTATUS); - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTRL); - CSI2_PRINT_REGISTER(iss, csi2->regs1, DBG_H); - CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_CFG); - CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_IRQSTATUS); - CSI2_PRINT_REGISTER(iss, csi2->regs1, SHORT_PACKET); - CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_IRQENABLE); - CSI2_PRINT_REGISTER(iss, csi2->regs1, DBG_P); - CSI2_PRINT_REGISTER(iss, csi2->regs1, TIMING); - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL1(0)); - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL2(0)); - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_DAT_OFST(0)); - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_PING_ADDR(0)); - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_PONG_ADDR(0)); - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_IRQENABLE(0)); - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_IRQSTATUS(0)); - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL3(0)); - - dev_dbg(iss->dev, "--------------------------------------------\n"); -} - -/* ----------------------------------------------------------------------------- - * Interrupt handling - */ - -/* - * csi2_isr_buffer - Does buffer handling at end-of-frame - * when writing to memory. - */ -static void csi2_isr_buffer(struct iss_csi2_device *csi2) -{ - struct iss_buffer *buffer; - - csi2_ctx_enable(csi2, 0, 0); - - buffer = omap4iss_video_buffer_next(&csi2->video_out); - - /* - * Let video queue operation restart engine if there is an underrun - * condition. - */ - if (!buffer) - return; - - csi2_set_outaddr(csi2, buffer->iss_addr); - csi2_ctx_enable(csi2, 0, 1); -} - -static void csi2_isr_ctx(struct iss_csi2_device *csi2, - struct iss_csi2_ctx_cfg *ctx) -{ - unsigned int n = ctx->ctxnum; - u32 status; - - status = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n)); - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n), status); - - if (omap4iss_module_sync_is_stopping(&csi2->wait, &csi2->stopping)) - return; - - /* Propagate frame number */ - if (status & CSI2_CTX_IRQ_FS) { - struct iss_pipeline *pipe = - to_iss_pipeline(&csi2->subdev.entity); - u16 frame; - u16 delta; - - frame = iss_reg_read(csi2->iss, csi2->regs1, - CSI2_CTX_CTRL2(ctx->ctxnum)) - >> CSI2_CTX_CTRL2_FRAME_SHIFT; - - if (frame == 0) { - /* A zero value means that the counter isn't implemented - * by the source. Increment the frame number in software - * in that case. - */ - atomic_inc(&pipe->frame_number); - } else { - /* Extend the 16 bit frame number to 32 bits by - * computing the delta between two consecutive CSI2 - * frame numbers and adding it to the software frame - * number. The hardware counter starts at 1 and wraps - * from 0xffff to 1 without going through 0, so subtract - * 1 when the counter wraps. - */ - delta = frame - ctx->frame; - if (frame < ctx->frame) - delta--; - ctx->frame = frame; - - atomic_add(delta, &pipe->frame_number); - } - } - - if (!(status & CSI2_CTX_IRQ_FE)) - return; - - /* Skip interrupts until we reach the frame skip count. The CSI2 will be - * automatically disabled, as the frame skip count has been programmed - * in the CSI2_CTx_CTRL1::COUNT field, so re-enable it. - * - * It would have been nice to rely on the FRAME_NUMBER interrupt instead - * but it turned out that the interrupt is only generated when the CSI2 - * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased - * correctly and reaches 0 when data is forwarded to the video port only - * but no interrupt arrives). Maybe a CSI2 hardware bug. - */ - if (csi2->frame_skip) { - csi2->frame_skip--; - if (csi2->frame_skip == 0) { - ctx->format_id = csi2_ctx_map_format(csi2); - csi2_ctx_config(csi2, ctx); - csi2_ctx_enable(csi2, n, 1); - } - return; - } - - if (csi2->output & CSI2_OUTPUT_MEMORY) - csi2_isr_buffer(csi2); -} - -/* - * omap4iss_csi2_isr - CSI2 interrupt handling. - */ -void omap4iss_csi2_isr(struct iss_csi2_device *csi2) -{ - struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); - u32 csi2_irqstatus, cpxio1_irqstatus; - struct iss_device *iss = csi2->iss; - - if (!csi2->available) - return; - - csi2_irqstatus = iss_reg_read(csi2->iss, csi2->regs1, CSI2_IRQSTATUS); - iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQSTATUS, csi2_irqstatus); - - /* Failure Cases */ - if (csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR) { - cpxio1_irqstatus = iss_reg_read(csi2->iss, csi2->regs1, - CSI2_COMPLEXIO_IRQSTATUS); - iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQSTATUS, - cpxio1_irqstatus); - dev_dbg(iss->dev, "CSI2: ComplexIO Error IRQ %x\n", - cpxio1_irqstatus); - pipe->error = true; - } - - if (csi2_irqstatus & (CSI2_IRQ_OCP_ERR | - CSI2_IRQ_SHORT_PACKET | - CSI2_IRQ_ECC_NO_CORRECTION | - CSI2_IRQ_COMPLEXIO_ERR | - CSI2_IRQ_FIFO_OVF)) { - dev_dbg(iss->dev, - "CSI2 Err: OCP:%d SHORT:%d ECC:%d CPXIO:%d OVF:%d\n", - csi2_irqstatus & CSI2_IRQ_OCP_ERR ? 1 : 0, - csi2_irqstatus & CSI2_IRQ_SHORT_PACKET ? 1 : 0, - csi2_irqstatus & CSI2_IRQ_ECC_NO_CORRECTION ? 1 : 0, - csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR ? 1 : 0, - csi2_irqstatus & CSI2_IRQ_FIFO_OVF ? 1 : 0); - pipe->error = true; - } - - /* Successful cases */ - if (csi2_irqstatus & CSI2_IRQ_CONTEXT0) - csi2_isr_ctx(csi2, &csi2->contexts[0]); - - if (csi2_irqstatus & CSI2_IRQ_ECC_CORRECTION) - dev_dbg(iss->dev, "CSI2: ECC correction done\n"); -} - -/* ----------------------------------------------------------------------------- - * ISS video operations - */ - -/* - * csi2_queue - Queues the first buffer when using memory output - * @video: The video node - * @buffer: buffer to queue - */ -static int csi2_queue(struct iss_video *video, struct iss_buffer *buffer) -{ - struct iss_csi2_device *csi2 = container_of(video, - struct iss_csi2_device, video_out); - - csi2_set_outaddr(csi2, buffer->iss_addr); - - /* - * If streaming was enabled before there was a buffer queued - * or underrun happened in the ISR, the hardware was not enabled - * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set. - * Enable it now. - */ - if (csi2->video_out.dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { - /* Enable / disable context 0 and IRQs */ - csi2_if_enable(csi2, 1); - csi2_ctx_enable(csi2, 0, 1); - iss_video_dmaqueue_flags_clr(&csi2->video_out); - } - - return 0; -} - -static const struct iss_video_operations csi2_issvideo_ops = { - .queue = csi2_queue, -}; - -/* ----------------------------------------------------------------------------- - * V4L2 subdev operations - */ - -static struct v4l2_mbus_framefmt * -__csi2_get_format(struct iss_csi2_device *csi2, - struct v4l2_subdev_state *sd_state, - unsigned int pad, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_state_get_format(sd_state, pad); - - return &csi2->formats[pad]; -} - -static void -csi2_try_format(struct iss_csi2_device *csi2, - struct v4l2_subdev_state *sd_state, - unsigned int pad, - struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) -{ - u32 pixelcode; - struct v4l2_mbus_framefmt *format; - const struct iss_format_info *info; - unsigned int i; - - switch (pad) { - case CSI2_PAD_SINK: - /* Clamp the width and height to valid range (1-8191). */ - for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) { - if (fmt->code == csi2_input_fmts[i]) - break; - } - - /* If not found, use SGRBG10 as default */ - if (i >= ARRAY_SIZE(csi2_input_fmts)) - fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; - - fmt->width = clamp_t(u32, fmt->width, 1, 8191); - fmt->height = clamp_t(u32, fmt->height, 1, 8191); - break; - - case CSI2_PAD_SOURCE: - /* Source format same as sink format, except for DPCM - * compression. - */ - pixelcode = fmt->code; - format = __csi2_get_format(csi2, sd_state, CSI2_PAD_SINK, - which); - memcpy(fmt, format, sizeof(*fmt)); - - /* - * Only Allow DPCM decompression, and check that the - * pattern is preserved - */ - info = omap4iss_video_format_info(fmt->code); - if (info->uncompressed == pixelcode) - fmt->code = pixelcode; - break; - } - - /* RGB, non-interlaced */ - fmt->colorspace = V4L2_COLORSPACE_SRGB; - fmt->field = V4L2_FIELD_NONE; -} - -/* - * csi2_enum_mbus_code - Handle pixel format enumeration - * @sd : pointer to v4l2 subdev structure - * @sd_state: V4L2 subdev state - * @code : pointer to v4l2_subdev_mbus_code_enum structure - * return -EINVAL or zero on success - */ -static int csi2_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - const struct iss_format_info *info; - - if (code->pad == CSI2_PAD_SINK) { - if (code->index >= ARRAY_SIZE(csi2_input_fmts)) - return -EINVAL; - - code->code = csi2_input_fmts[code->index]; - } else { - format = __csi2_get_format(csi2, sd_state, CSI2_PAD_SINK, - code->which); - switch (code->index) { - case 0: - /* Passthrough sink pad code */ - code->code = format->code; - break; - case 1: - /* Uncompressed code */ - info = omap4iss_video_format_info(format->code); - if (info->uncompressed == format->code) - return -EINVAL; - - code->code = info->uncompressed; - break; - default: - return -EINVAL; - } - } - - return 0; -} - -static int csi2_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt format; - - if (fse->index != 0) - return -EINVAL; - - format.code = fse->code; - format.width = 1; - format.height = 1; - csi2_try_format(csi2, sd_state, fse->pad, &format, fse->which); - fse->min_width = format.width; - fse->min_height = format.height; - - if (format.code != fse->code) - return -EINVAL; - - format.code = fse->code; - format.width = -1; - format.height = -1; - csi2_try_format(csi2, sd_state, fse->pad, &format, fse->which); - fse->max_width = format.width; - fse->max_height = format.height; - - return 0; -} - -/* - * csi2_get_format - Handle get format by pads subdev method - * @sd : pointer to v4l2 subdev structure - * @sd_state: V4L2 subdev state - * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on success - */ -static int csi2_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __csi2_get_format(csi2, sd_state, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - fmt->format = *format; - return 0; -} - -/* - * csi2_set_format - Handle set format by pads subdev method - * @sd : pointer to v4l2 subdev structure - * @sd_state: V4L2 subdev state - * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on success - */ -static int csi2_set_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __csi2_get_format(csi2, sd_state, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - csi2_try_format(csi2, sd_state, fmt->pad, &fmt->format, fmt->which); - *format = fmt->format; - - /* Propagate the format from sink to source */ - if (fmt->pad == CSI2_PAD_SINK) { - format = __csi2_get_format(csi2, sd_state, CSI2_PAD_SOURCE, - fmt->which); - *format = fmt->format; - csi2_try_format(csi2, sd_state, CSI2_PAD_SOURCE, format, - fmt->which); - } - - return 0; -} - -static int csi2_link_validate(struct v4l2_subdev *sd, struct media_link *link, - struct v4l2_subdev_format *source_fmt, - struct v4l2_subdev_format *sink_fmt) -{ - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); - struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); - int rval; - - pipe->external = media_entity_to_v4l2_subdev(link->source->entity); - rval = omap4iss_get_external_info(pipe, link); - if (rval < 0) - return rval; - - return v4l2_subdev_link_validate_default(sd, link, source_fmt, - sink_fmt); -} - -/* - * csi2_init_formats - Initialize formats on all pads - * @sd: ISS CSI2 V4L2 subdevice - * @fh: V4L2 subdev file handle - * - * Initialize all pad formats with default values. If fh is not NULL, try - * formats are initialized on the file handle. Otherwise active formats are - * initialized on the device. - */ -static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - struct v4l2_subdev_format format; - - memset(&format, 0, sizeof(format)); - format.pad = CSI2_PAD_SINK; - format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; - format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10; - format.format.width = 4096; - format.format.height = 4096; - csi2_set_format(sd, fh ? fh->state : NULL, &format); - - return 0; -} - -/* - * csi2_set_stream - Enable/Disable streaming on the CSI2 module - * @sd: ISS CSI2 V4L2 subdevice - * @enable: ISS pipeline stream state - * - * Return 0 on success or a negative error code otherwise. - */ -static int csi2_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); - struct iss_device *iss = csi2->iss; - struct iss_video *video_out = &csi2->video_out; - int ret = 0; - - if (csi2->state == ISS_PIPELINE_STREAM_STOPPED) { - if (enable == ISS_PIPELINE_STREAM_STOPPED) - return 0; - - omap4iss_subclk_enable(iss, csi2->subclk); - } - - switch (enable) { - case ISS_PIPELINE_STREAM_CONTINUOUS: { - ret = omap4iss_csiphy_config(iss, sd); - if (ret < 0) - return ret; - - if (omap4iss_csiphy_acquire(csi2->phy) < 0) - return -ENODEV; - csi2_configure(csi2); - csi2_print_status(csi2); - - /* - * When outputting to memory with no buffer available, let the - * buffer queue handler start the hardware. A DMA queue flag - * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is - * a buffer available. - */ - if (csi2->output & CSI2_OUTPUT_MEMORY && - !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED)) - break; - /* Enable context 0 and IRQs */ - atomic_set(&csi2->stopping, 0); - csi2_ctx_enable(csi2, 0, 1); - csi2_if_enable(csi2, 1); - iss_video_dmaqueue_flags_clr(video_out); - break; - } - case ISS_PIPELINE_STREAM_STOPPED: - if (csi2->state == ISS_PIPELINE_STREAM_STOPPED) - return 0; - if (omap4iss_module_sync_idle(&sd->entity, &csi2->wait, - &csi2->stopping)) - ret = -ETIMEDOUT; - csi2_ctx_enable(csi2, 0, 0); - csi2_if_enable(csi2, 0); - csi2_irq_ctx_set(csi2, 0); - omap4iss_csiphy_release(csi2->phy); - omap4iss_subclk_disable(iss, csi2->subclk); - iss_video_dmaqueue_flags_clr(video_out); - break; - } - - csi2->state = enable; - return ret; -} - -/* subdev video operations */ -static const struct v4l2_subdev_video_ops csi2_video_ops = { - .s_stream = csi2_set_stream, -}; - -/* subdev pad operations */ -static const struct v4l2_subdev_pad_ops csi2_pad_ops = { - .enum_mbus_code = csi2_enum_mbus_code, - .enum_frame_size = csi2_enum_frame_size, - .get_fmt = csi2_get_format, - .set_fmt = csi2_set_format, - .link_validate = csi2_link_validate, -}; - -/* subdev operations */ -static const struct v4l2_subdev_ops csi2_ops = { - .video = &csi2_video_ops, - .pad = &csi2_pad_ops, -}; - -/* subdev internal operations */ -static const struct v4l2_subdev_internal_ops csi2_internal_ops = { - .open = csi2_init_formats, -}; - -/* ----------------------------------------------------------------------------- - * Media entity operations - */ - -/* - * csi2_link_setup - Setup CSI2 connections. - * @entity : Pointer to media entity structure - * @local : Pointer to local pad array - * @remote : Pointer to remote pad array - * @flags : Link flags - * return -EINVAL or zero on success - */ -static int csi2_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); - struct iss_csi2_ctrl_cfg *ctrl = &csi2->ctrl; - unsigned int index = local->index; - - /* FIXME: this is actually a hack! */ - if (is_media_entity_v4l2_subdev(remote->entity)) - index |= 2 << 16; - - /* - * The ISS core doesn't support pipelines with multiple video outputs. - * Revisit this when it will be implemented, and return -EBUSY for now. - */ - - switch (index) { - case CSI2_PAD_SOURCE: - if (flags & MEDIA_LNK_FL_ENABLED) { - if (csi2->output & ~CSI2_OUTPUT_MEMORY) - return -EBUSY; - csi2->output |= CSI2_OUTPUT_MEMORY; - } else { - csi2->output &= ~CSI2_OUTPUT_MEMORY; - } - break; - - case CSI2_PAD_SOURCE | 2 << 16: - if (flags & MEDIA_LNK_FL_ENABLED) { - if (csi2->output & ~CSI2_OUTPUT_IPIPEIF) - return -EBUSY; - csi2->output |= CSI2_OUTPUT_IPIPEIF; - } else { - csi2->output &= ~CSI2_OUTPUT_IPIPEIF; - } - break; - - default: - /* Link from camera to CSI2 is fixed... */ - return -EINVAL; - } - - ctrl->vp_only_enable = csi2->output & CSI2_OUTPUT_MEMORY ? false : true; - ctrl->vp_clk_enable = !!(csi2->output & CSI2_OUTPUT_IPIPEIF); - - return 0; -} - -/* media operations */ -static const struct media_entity_operations csi2_media_ops = { - .link_setup = csi2_link_setup, - .link_validate = v4l2_subdev_link_validate, -}; - -void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2) -{ - v4l2_device_unregister_subdev(&csi2->subdev); - omap4iss_video_unregister(&csi2->video_out); -} - -int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2, - struct v4l2_device *vdev) -{ - int ret; - - /* Register the subdev and video nodes. */ - ret = v4l2_device_register_subdev(vdev, &csi2->subdev); - if (ret < 0) - goto error; - - ret = omap4iss_video_register(&csi2->video_out, vdev); - if (ret < 0) - goto error; - - return 0; - -error: - omap4iss_csi2_unregister_entities(csi2); - return ret; -} - -/* ----------------------------------------------------------------------------- - * ISS CSI2 initialisation and cleanup - */ - -/* - * csi2_init_entities - Initialize subdev and media entity. - * @csi2: Pointer to csi2 structure. - * return -ENOMEM or zero on success - */ -static int csi2_init_entities(struct iss_csi2_device *csi2, const char *subname) -{ - struct v4l2_subdev *sd = &csi2->subdev; - struct media_pad *pads = csi2->pads; - struct media_entity *me = &sd->entity; - int ret; - char name[32]; - - v4l2_subdev_init(sd, &csi2_ops); - sd->internal_ops = &csi2_internal_ops; - snprintf(name, sizeof(name), "CSI2%s", subname); - snprintf(sd->name, sizeof(sd->name), "OMAP4 ISS %s", name); - - sd->grp_id = BIT(16); /* group ID for iss subdevs */ - v4l2_set_subdevdata(sd, csi2); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - - me->ops = &csi2_media_ops; - ret = media_entity_pads_init(me, CSI2_PADS_NUM, pads); - if (ret < 0) - return ret; - - csi2_init_formats(sd, NULL); - - /* Video device node */ - csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - csi2->video_out.ops = &csi2_issvideo_ops; - csi2->video_out.bpl_alignment = 32; - csi2->video_out.bpl_zero_padding = 1; - csi2->video_out.bpl_max = 0x1ffe0; - csi2->video_out.iss = csi2->iss; - csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; - - ret = omap4iss_video_init(&csi2->video_out, name); - if (ret < 0) - goto error_video; - - return 0; - -error_video: - media_entity_cleanup(&csi2->subdev.entity); - return ret; -} - -/* - * omap4iss_csi2_init - Routine for module driver init - */ -int omap4iss_csi2_init(struct iss_device *iss) -{ - struct iss_csi2_device *csi2a = &iss->csi2a; - struct iss_csi2_device *csi2b = &iss->csi2b; - int ret; - - csi2a->iss = iss; - csi2a->available = 1; - csi2a->regs1 = OMAP4_ISS_MEM_CSI2_A_REGS1; - csi2a->phy = &iss->csiphy1; - csi2a->subclk = OMAP4_ISS_SUBCLK_CSI2_A; - csi2a->state = ISS_PIPELINE_STREAM_STOPPED; - init_waitqueue_head(&csi2a->wait); - - ret = csi2_init_entities(csi2a, "a"); - if (ret < 0) - return ret; - - csi2b->iss = iss; - csi2b->available = 1; - csi2b->regs1 = OMAP4_ISS_MEM_CSI2_B_REGS1; - csi2b->phy = &iss->csiphy2; - csi2b->subclk = OMAP4_ISS_SUBCLK_CSI2_B; - csi2b->state = ISS_PIPELINE_STREAM_STOPPED; - init_waitqueue_head(&csi2b->wait); - - ret = csi2_init_entities(csi2b, "b"); - if (ret < 0) - return ret; - - return 0; -} - -/* - * omap4iss_csi2_create_links() - CSI2 pads links creation - * @iss: Pointer to ISS device - * - * return negative error code or zero on success - */ -int omap4iss_csi2_create_links(struct iss_device *iss) -{ - struct iss_csi2_device *csi2a = &iss->csi2a; - struct iss_csi2_device *csi2b = &iss->csi2b; - int ret; - - /* Connect the CSI2a subdev to the video node. */ - ret = media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE, - &csi2a->video_out.video.entity, 0, 0); - if (ret < 0) - return ret; - - /* Connect the CSI2b subdev to the video node. */ - ret = media_create_pad_link(&csi2b->subdev.entity, CSI2_PAD_SOURCE, - &csi2b->video_out.video.entity, 0, 0); - if (ret < 0) - return ret; - - return 0; -} - -/* - * omap4iss_csi2_cleanup - Routine for module driver cleanup - */ -void omap4iss_csi2_cleanup(struct iss_device *iss) -{ - struct iss_csi2_device *csi2a = &iss->csi2a; - struct iss_csi2_device *csi2b = &iss->csi2b; - - omap4iss_video_cleanup(&csi2a->video_out); - media_entity_cleanup(&csi2a->subdev.entity); - - omap4iss_video_cleanup(&csi2b->video_out); - media_entity_cleanup(&csi2b->subdev.entity); -} diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h deleted file mode 100644 index 3f7fd9cff41d..000000000000 --- a/drivers/staging/media/omap4iss/iss_csi2.h +++ /dev/null @@ -1,155 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * TI OMAP4 ISS V4L2 Driver - CSI2 module - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#ifndef OMAP4_ISS_CSI2_H -#define OMAP4_ISS_CSI2_H - -#include -#include - -#include "iss_video.h" - -struct iss_csiphy; - -/* This is not an exhaustive list */ -enum iss_csi2_pix_formats { - CSI2_PIX_FMT_OTHERS = 0, - CSI2_PIX_FMT_YUV422_8BIT = 0x1e, - CSI2_PIX_FMT_YUV422_8BIT_VP = 0x9e, - CSI2_PIX_FMT_YUV422_8BIT_VP16 = 0xde, - CSI2_PIX_FMT_RAW10_EXP16 = 0xab, - CSI2_PIX_FMT_RAW10_EXP16_VP = 0x12f, - CSI2_PIX_FMT_RAW8 = 0x2a, - CSI2_PIX_FMT_RAW8_DPCM10_EXP16 = 0x2aa, - CSI2_PIX_FMT_RAW8_DPCM10_VP = 0x32a, - CSI2_PIX_FMT_RAW8_VP = 0x12a, - CSI2_USERDEF_8BIT_DATA1_DPCM10_VP = 0x340, - CSI2_USERDEF_8BIT_DATA1_DPCM10 = 0x2c0, - CSI2_USERDEF_8BIT_DATA1 = 0x40, -}; - -enum iss_csi2_irqevents { - OCP_ERR_IRQ = 0x4000, - SHORT_PACKET_IRQ = 0x2000, - ECC_CORRECTION_IRQ = 0x1000, - ECC_NO_CORRECTION_IRQ = 0x800, - COMPLEXIO2_ERR_IRQ = 0x400, - COMPLEXIO1_ERR_IRQ = 0x200, - FIFO_OVF_IRQ = 0x100, - CONTEXT7 = 0x80, - CONTEXT6 = 0x40, - CONTEXT5 = 0x20, - CONTEXT4 = 0x10, - CONTEXT3 = 0x8, - CONTEXT2 = 0x4, - CONTEXT1 = 0x2, - CONTEXT0 = 0x1, -}; - -enum iss_csi2_ctx_irqevents { - CTX_ECC_CORRECTION = 0x100, - CTX_LINE_NUMBER = 0x80, - CTX_FRAME_NUMBER = 0x40, - CTX_CS = 0x20, - CTX_LE = 0x8, - CTX_LS = 0x4, - CTX_FE = 0x2, - CTX_FS = 0x1, -}; - -enum iss_csi2_frame_mode { - ISS_CSI2_FRAME_IMMEDIATE, - ISS_CSI2_FRAME_AFTERFEC, -}; - -#define ISS_CSI2_MAX_CTX_NUM 7 - -struct iss_csi2_ctx_cfg { - u8 ctxnum; /* context number 0 - 7 */ - u8 dpcm_decompress; - - /* Fields in CSI2_CTx_CTRL2 - locked by CSI2_CTx_CTRL1.CTX_EN */ - u8 virtual_id; - u16 format_id; /* as in CSI2_CTx_CTRL2[9:0] */ - u8 dpcm_predictor; /* 1: simple, 0: advanced */ - u16 frame; - - /* Fields in CSI2_CTx_CTRL1/3 - Shadowed */ - u16 alpha; - u16 data_offset; - u32 ping_addr; - u32 pong_addr; - u8 eof_enabled; - u8 eol_enabled; - u8 checksum_enabled; - u8 enabled; -}; - -struct iss_csi2_timing_cfg { - u8 ionum; /* IO1 or IO2 as in CSI2_TIMING */ - unsigned force_rx_mode:1; - unsigned stop_state_16x:1; - unsigned stop_state_4x:1; - u16 stop_state_counter; -}; - -struct iss_csi2_ctrl_cfg { - bool vp_clk_enable; - bool vp_only_enable; - u8 vp_out_ctrl; - enum iss_csi2_frame_mode frame_mode; - bool ecc_enable; - bool if_enable; -}; - -#define CSI2_PAD_SINK 0 -#define CSI2_PAD_SOURCE 1 -#define CSI2_PADS_NUM 2 - -#define CSI2_OUTPUT_IPIPEIF BIT(0) -#define CSI2_OUTPUT_MEMORY BIT(1) - -struct iss_csi2_device { - struct v4l2_subdev subdev; - struct media_pad pads[CSI2_PADS_NUM]; - struct v4l2_mbus_framefmt formats[CSI2_PADS_NUM]; - - struct iss_video video_out; - struct iss_device *iss; - - u8 available; /* Is the IP present on the silicon? */ - - /* memory resources, as defined in enum iss_mem_resources */ - unsigned int regs1; - unsigned int regs2; - /* ISP subclock, as defined in enum iss_isp_subclk_resource */ - unsigned int subclk; - - u32 output; /* output to IPIPEIF, memory or both? */ - bool dpcm_decompress; - unsigned int frame_skip; - - struct iss_csiphy *phy; - struct iss_csi2_ctx_cfg contexts[ISS_CSI2_MAX_CTX_NUM + 1]; - struct iss_csi2_timing_cfg timing[2]; - struct iss_csi2_ctrl_cfg ctrl; - enum iss_pipeline_stream_state state; - wait_queue_head_t wait; - atomic_t stopping; -}; - -void omap4iss_csi2_isr(struct iss_csi2_device *csi2); -int omap4iss_csi2_reset(struct iss_csi2_device *csi2); -int omap4iss_csi2_init(struct iss_device *iss); -int omap4iss_csi2_create_links(struct iss_device *iss); -void omap4iss_csi2_cleanup(struct iss_device *iss); -void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2); -int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2, - struct v4l2_device *vdev); -#endif /* OMAP4_ISS_CSI2_H */ diff --git a/drivers/staging/media/omap4iss/iss_csiphy.c b/drivers/staging/media/omap4iss/iss_csiphy.c deleted file mode 100644 index 96f2ce045138..000000000000 --- a/drivers/staging/media/omap4iss/iss_csiphy.c +++ /dev/null @@ -1,277 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * TI OMAP4 ISS V4L2 Driver - CSI PHY module - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#include -#include -#include - -#include "../../../../arch/arm/mach-omap2/control.h" - -#include "iss.h" -#include "iss_regs.h" -#include "iss_csiphy.h" - -/* - * csiphy_lanes_config - Configuration of CSIPHY lanes. - * - * Updates HW configuration. - * Called with phy->mutex taken. - */ -static void csiphy_lanes_config(struct iss_csiphy *phy) -{ - unsigned int i; - u32 reg; - - reg = iss_reg_read(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG); - - for (i = 0; i < phy->max_data_lanes; i++) { - reg &= ~(CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) | - CSI2_COMPLEXIO_CFG_DATA_POSITION_MASK(i + 1)); - reg |= (phy->lanes.data[i].pol ? - CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) : 0); - reg |= (phy->lanes.data[i].pos << - CSI2_COMPLEXIO_CFG_DATA_POSITION_SHIFT(i + 1)); - } - - reg &= ~(CSI2_COMPLEXIO_CFG_CLOCK_POL | - CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK); - reg |= phy->lanes.clk.pol ? CSI2_COMPLEXIO_CFG_CLOCK_POL : 0; - reg |= phy->lanes.clk.pos << CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT; - - iss_reg_write(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG, reg); -} - -/* - * csiphy_set_power - * @power: Power state to be set. - * - * Returns 0 if successful, or -EBUSY if the retry count is exceeded. - */ -static int csiphy_set_power(struct iss_csiphy *phy, u32 power) -{ - u32 reg; - u8 retry_count; - - iss_reg_update(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG, - CSI2_COMPLEXIO_CFG_PWD_CMD_MASK, - power | CSI2_COMPLEXIO_CFG_PWR_AUTO); - - retry_count = 0; - do { - udelay(1); - reg = iss_reg_read(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG) - & CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK; - - if (reg != power >> 2) - retry_count++; - - } while ((reg != power >> 2) && (retry_count < 250)); - - if (retry_count == 250) { - dev_err(phy->iss->dev, "CSI2 CIO set power failed!\n"); - return -EBUSY; - } - - return 0; -} - -/* - * csiphy_dphy_config - Configure CSI2 D-PHY parameters. - * - * Called with phy->mutex taken. - */ -static void csiphy_dphy_config(struct iss_csiphy *phy) -{ - u32 reg; - - /* Set up REGISTER0 */ - reg = phy->dphy.ths_term << REGISTER0_THS_TERM_SHIFT; - reg |= phy->dphy.ths_settle << REGISTER0_THS_SETTLE_SHIFT; - - iss_reg_write(phy->iss, phy->phy_regs, REGISTER0, reg); - - /* Set up REGISTER1 */ - reg = phy->dphy.tclk_term << REGISTER1_TCLK_TERM_SHIFT; - reg |= phy->dphy.tclk_miss << REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT; - reg |= phy->dphy.tclk_settle << REGISTER1_TCLK_SETTLE_SHIFT; - reg |= 0xb8 << REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT; - - iss_reg_write(phy->iss, phy->phy_regs, REGISTER1, reg); -} - -/* - * TCLK values are OK at their reset values - */ -#define TCLK_TERM 0 -#define TCLK_MISS 1 -#define TCLK_SETTLE 14 - -int omap4iss_csiphy_config(struct iss_device *iss, - struct v4l2_subdev *csi2_subdev) -{ - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(csi2_subdev); - struct iss_pipeline *pipe = to_iss_pipeline(&csi2_subdev->entity); - struct iss_v4l2_subdevs_group *subdevs = pipe->external->host_priv; - struct iss_csiphy_dphy_cfg csi2phy; - int csi2_ddrclk_khz; - struct iss_csiphy_lanes_cfg *lanes; - unsigned int used_lanes = 0; - u32 cam_rx_ctrl; - unsigned int i; - - lanes = &subdevs->bus.csi2.lanecfg; - - /* - * SCM.CONTROL_CAMERA_RX - * - bit [31] : CSIPHY2 lane 2 enable (4460+ only) - * - bit [30:29] : CSIPHY2 per-lane enable (1 to 0) - * - bit [28:24] : CSIPHY1 per-lane enable (4 to 0) - * - bit [21] : CSIPHY2 CTRLCLK enable - * - bit [20:19] : CSIPHY2 config: 00 d-phy, 01/10 ccp2 - * - bit [18] : CSIPHY1 CTRLCLK enable - * - bit [17:16] : CSIPHY1 config: 00 d-phy, 01/10 ccp2 - */ - /* - * TODO: When implementing DT support specify the CONTROL_CAMERA_RX - * register offset in the syscon property instead of hardcoding it. - */ - regmap_read(iss->syscon, 0x68, &cam_rx_ctrl); - - if (subdevs->interface == ISS_INTERFACE_CSI2A_PHY1) { - cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI21_LANEENABLE_MASK | - OMAP4_CAMERARX_CSI21_CAMMODE_MASK); - /* NOTE: Leave CSIPHY1 config to 0x0: D-PHY mode */ - /* Enable all lanes for now */ - cam_rx_ctrl |= - 0x1f << OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT; - /* Enable CTRLCLK */ - cam_rx_ctrl |= OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK; - } - - if (subdevs->interface == ISS_INTERFACE_CSI2B_PHY2) { - cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI22_LANEENABLE_MASK | - OMAP4_CAMERARX_CSI22_CAMMODE_MASK); - /* NOTE: Leave CSIPHY2 config to 0x0: D-PHY mode */ - /* Enable all lanes for now */ - cam_rx_ctrl |= - 0x3 << OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT; - /* Enable CTRLCLK */ - cam_rx_ctrl |= OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK; - } - - regmap_write(iss->syscon, 0x68, cam_rx_ctrl); - - /* Reset used lane count */ - csi2->phy->used_data_lanes = 0; - - /* Clock and data lanes verification */ - for (i = 0; i < csi2->phy->max_data_lanes; i++) { - if (lanes->data[i].pos == 0) - continue; - - if (lanes->data[i].pol > 1 || - lanes->data[i].pos > (csi2->phy->max_data_lanes + 1)) - return -EINVAL; - - if (used_lanes & (1 << lanes->data[i].pos)) - return -EINVAL; - - used_lanes |= 1 << lanes->data[i].pos; - csi2->phy->used_data_lanes++; - } - - if (lanes->clk.pol > 1 || - lanes->clk.pos > (csi2->phy->max_data_lanes + 1)) - return -EINVAL; - - if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos)) - return -EINVAL; - - csi2_ddrclk_khz = pipe->external_rate / 1000 - / (2 * csi2->phy->used_data_lanes) - * pipe->external_bpp; - - /* - * THS_TERM: Programmed value = ceil(12.5 ns/DDRClk period) - 1. - * THS_SETTLE: Programmed value = ceil(90 ns/DDRClk period) + 3. - */ - csi2phy.ths_term = DIV_ROUND_UP(25 * csi2_ddrclk_khz, 2000000) - 1; - csi2phy.ths_settle = DIV_ROUND_UP(90 * csi2_ddrclk_khz, 1000000) + 3; - csi2phy.tclk_term = TCLK_TERM; - csi2phy.tclk_miss = TCLK_MISS; - csi2phy.tclk_settle = TCLK_SETTLE; - - mutex_lock(&csi2->phy->mutex); - csi2->phy->dphy = csi2phy; - csi2->phy->lanes = *lanes; - mutex_unlock(&csi2->phy->mutex); - - return 0; -} - -int omap4iss_csiphy_acquire(struct iss_csiphy *phy) -{ - int rval; - - mutex_lock(&phy->mutex); - - rval = omap4iss_csi2_reset(phy->csi2); - if (rval) - goto done; - - csiphy_dphy_config(phy); - csiphy_lanes_config(phy); - - rval = csiphy_set_power(phy, CSI2_COMPLEXIO_CFG_PWD_CMD_ON); - if (rval) - goto done; - - phy->phy_in_use = 1; - -done: - mutex_unlock(&phy->mutex); - return rval; -} - -void omap4iss_csiphy_release(struct iss_csiphy *phy) -{ - mutex_lock(&phy->mutex); - if (phy->phy_in_use) { - csiphy_set_power(phy, CSI2_COMPLEXIO_CFG_PWD_CMD_OFF); - phy->phy_in_use = 0; - } - mutex_unlock(&phy->mutex); -} - -/* - * omap4iss_csiphy_init - Initialize the CSI PHY frontends - */ -int omap4iss_csiphy_init(struct iss_device *iss) -{ - struct iss_csiphy *phy1 = &iss->csiphy1; - struct iss_csiphy *phy2 = &iss->csiphy2; - - phy1->iss = iss; - phy1->csi2 = &iss->csi2a; - phy1->max_data_lanes = ISS_CSIPHY1_NUM_DATA_LANES; - phy1->used_data_lanes = 0; - phy1->cfg_regs = OMAP4_ISS_MEM_CSI2_A_REGS1; - phy1->phy_regs = OMAP4_ISS_MEM_CAMERARX_CORE1; - mutex_init(&phy1->mutex); - - phy2->iss = iss; - phy2->csi2 = &iss->csi2b; - phy2->max_data_lanes = ISS_CSIPHY2_NUM_DATA_LANES; - phy2->used_data_lanes = 0; - phy2->cfg_regs = OMAP4_ISS_MEM_CSI2_B_REGS1; - phy2->phy_regs = OMAP4_ISS_MEM_CAMERARX_CORE2; - mutex_init(&phy2->mutex); - - return 0; -} diff --git a/drivers/staging/media/omap4iss/iss_csiphy.h b/drivers/staging/media/omap4iss/iss_csiphy.h deleted file mode 100644 index 44408e4fcf3b..000000000000 --- a/drivers/staging/media/omap4iss/iss_csiphy.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * TI OMAP4 ISS V4L2 Driver - CSI PHY module - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#ifndef OMAP4_ISS_CSI_PHY_H -#define OMAP4_ISS_CSI_PHY_H - -#include - -struct iss_csi2_device; - -struct iss_csiphy_dphy_cfg { - u8 ths_term; - u8 ths_settle; - u8 tclk_term; - unsigned tclk_miss:1; - u8 tclk_settle; -}; - -struct iss_csiphy { - struct iss_device *iss; - struct mutex mutex; /* serialize csiphy configuration */ - u8 phy_in_use; - struct iss_csi2_device *csi2; - - /* memory resources, as defined in enum iss_mem_resources */ - unsigned int cfg_regs; - unsigned int phy_regs; - - u8 max_data_lanes; /* number of CSI2 Data Lanes supported */ - u8 used_data_lanes; /* number of CSI2 Data Lanes used */ - struct iss_csiphy_lanes_cfg lanes; - struct iss_csiphy_dphy_cfg dphy; -}; - -int omap4iss_csiphy_config(struct iss_device *iss, - struct v4l2_subdev *csi2_subdev); -int omap4iss_csiphy_acquire(struct iss_csiphy *phy); -void omap4iss_csiphy_release(struct iss_csiphy *phy); -int omap4iss_csiphy_init(struct iss_device *iss); - -#endif /* OMAP4_ISS_CSI_PHY_H */ diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c deleted file mode 100644 index 4a4eae290d65..000000000000 --- a/drivers/staging/media/omap4iss/iss_ipipe.c +++ /dev/null @@ -1,579 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "iss.h" -#include "iss_regs.h" -#include "iss_ipipe.h" - -static struct v4l2_mbus_framefmt * -__ipipe_get_format(struct iss_ipipe_device *ipipe, - struct v4l2_subdev_state *sd_state, - unsigned int pad, - enum v4l2_subdev_format_whence which); - -static const unsigned int ipipe_fmts[] = { - MEDIA_BUS_FMT_SGRBG10_1X10, - MEDIA_BUS_FMT_SRGGB10_1X10, - MEDIA_BUS_FMT_SBGGR10_1X10, - MEDIA_BUS_FMT_SGBRG10_1X10, -}; - -/* - * ipipe_print_status - Print current IPIPE Module register values. - * @ipipe: Pointer to ISS ISP IPIPE device. - * - * Also prints other debug information stored in the IPIPE module. - */ -#define IPIPE_PRINT_REGISTER(iss, name)\ - dev_dbg(iss->dev, "###IPIPE " #name "=0x%08x\n", \ - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_##name)) - -static void ipipe_print_status(struct iss_ipipe_device *ipipe) -{ - struct iss_device *iss = to_iss_device(ipipe); - - dev_dbg(iss->dev, "-------------IPIPE Register dump-------------\n"); - - IPIPE_PRINT_REGISTER(iss, SRC_EN); - IPIPE_PRINT_REGISTER(iss, SRC_MODE); - IPIPE_PRINT_REGISTER(iss, SRC_FMT); - IPIPE_PRINT_REGISTER(iss, SRC_COL); - IPIPE_PRINT_REGISTER(iss, SRC_VPS); - IPIPE_PRINT_REGISTER(iss, SRC_VSZ); - IPIPE_PRINT_REGISTER(iss, SRC_HPS); - IPIPE_PRINT_REGISTER(iss, SRC_HSZ); - IPIPE_PRINT_REGISTER(iss, GCK_MMR); - IPIPE_PRINT_REGISTER(iss, YUV_PHS); - - dev_dbg(iss->dev, "-----------------------------------------------\n"); -} - -/* - * ipipe_enable - Enable/Disable IPIPE. - * @enable: enable flag - * - */ -static void ipipe_enable(struct iss_ipipe_device *ipipe, u8 enable) -{ - struct iss_device *iss = to_iss_device(ipipe); - - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_EN, - IPIPE_SRC_EN_EN, enable ? IPIPE_SRC_EN_EN : 0); -} - -/* ----------------------------------------------------------------------------- - * Format- and pipeline-related configuration helpers - */ - -static void ipipe_configure(struct iss_ipipe_device *ipipe) -{ - struct iss_device *iss = to_iss_device(ipipe); - struct v4l2_mbus_framefmt *format; - - /* IPIPE_PAD_SINK */ - format = &ipipe->formats[IPIPE_PAD_SINK]; - - /* NOTE: Currently just supporting pipeline IN: RGB, OUT: YUV422 */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_FMT, - IPIPE_SRC_FMT_RAW2YUV); - - /* Enable YUV444 -> YUV422 conversion */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_YUV_PHS, - IPIPE_YUV_PHS_LPF); - - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_VPS, 0); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_HPS, 0); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_VSZ, - (format->height - 2) & IPIPE_SRC_VSZ_MASK); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_HSZ, - (format->width - 1) & IPIPE_SRC_HSZ_MASK); - - /* Ignore ipipeif_wrt signal, and operate on-the-fly. */ - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_MODE, - IPIPE_SRC_MODE_WRT | IPIPE_SRC_MODE_OST); - - /* HACK: Values tuned for Ducati SW (OV) */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_COL, - IPIPE_SRC_COL_EE_B | IPIPE_SRC_COL_EO_GB | - IPIPE_SRC_COL_OE_GR | IPIPE_SRC_COL_OO_R); - - /* IPIPE_PAD_SOURCE_VP */ - format = &ipipe->formats[IPIPE_PAD_SOURCE_VP]; - /* Do nothing? */ -} - -/* ----------------------------------------------------------------------------- - * V4L2 subdev operations - */ - -/* - * ipipe_set_stream - Enable/Disable streaming on the IPIPE module - * @sd: ISP IPIPE V4L2 subdevice - * @enable: Enable/disable stream - */ -static int ipipe_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct iss_device *iss = to_iss_device(ipipe); - int ret = 0; - - if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED) { - if (enable == ISS_PIPELINE_STREAM_STOPPED) - return 0; - - omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE); - - /* Enable clk_arm_g0 */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_GCK_MMR, - IPIPE_GCK_MMR_REG); - - /* Enable clk_pix_g[3:0] */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_GCK_PIX, - IPIPE_GCK_PIX_G3 | IPIPE_GCK_PIX_G2 | - IPIPE_GCK_PIX_G1 | IPIPE_GCK_PIX_G0); - } - - switch (enable) { - case ISS_PIPELINE_STREAM_CONTINUOUS: - - ipipe_configure(ipipe); - ipipe_print_status(ipipe); - - atomic_set(&ipipe->stopping, 0); - ipipe_enable(ipipe, 1); - break; - - case ISS_PIPELINE_STREAM_STOPPED: - if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED) - return 0; - if (omap4iss_module_sync_idle(&sd->entity, &ipipe->wait, - &ipipe->stopping)) - ret = -ETIMEDOUT; - - ipipe_enable(ipipe, 0); - omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE); - break; - } - - ipipe->state = enable; - return ret; -} - -static struct v4l2_mbus_framefmt * -__ipipe_get_format(struct iss_ipipe_device *ipipe, - struct v4l2_subdev_state *sd_state, - unsigned int pad, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_state_get_format(sd_state, pad); - - return &ipipe->formats[pad]; -} - -/* - * ipipe_try_format - Try video format on a pad - * @ipipe: ISS IPIPE device - * @sd_state: V4L2 subdev state - * @pad: Pad number - * @fmt: Format - */ -static void -ipipe_try_format(struct iss_ipipe_device *ipipe, - struct v4l2_subdev_state *sd_state, - unsigned int pad, - struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) -{ - struct v4l2_mbus_framefmt *format; - unsigned int width = fmt->width; - unsigned int height = fmt->height; - unsigned int i; - - switch (pad) { - case IPIPE_PAD_SINK: - for (i = 0; i < ARRAY_SIZE(ipipe_fmts); i++) { - if (fmt->code == ipipe_fmts[i]) - break; - } - - /* If not found, use SGRBG10 as default */ - if (i >= ARRAY_SIZE(ipipe_fmts)) - fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; - - /* Clamp the input size. */ - fmt->width = clamp_t(u32, width, 1, 8192); - fmt->height = clamp_t(u32, height, 1, 8192); - fmt->colorspace = V4L2_COLORSPACE_SRGB; - break; - - case IPIPE_PAD_SOURCE_VP: - format = __ipipe_get_format(ipipe, sd_state, IPIPE_PAD_SINK, - which); - memcpy(fmt, format, sizeof(*fmt)); - - fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; - fmt->width = clamp_t(u32, width, 32, fmt->width); - fmt->height = clamp_t(u32, height, 32, fmt->height); - fmt->colorspace = V4L2_COLORSPACE_JPEG; - break; - } - - fmt->field = V4L2_FIELD_NONE; -} - -/* - * ipipe_enum_mbus_code - Handle pixel format enumeration - * @sd : pointer to v4l2 subdev structure - * @sd_state: V4L2 subdev state - * @code : pointer to v4l2_subdev_mbus_code_enum structure - * return -EINVAL or zero on success - */ -static int ipipe_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - switch (code->pad) { - case IPIPE_PAD_SINK: - if (code->index >= ARRAY_SIZE(ipipe_fmts)) - return -EINVAL; - - code->code = ipipe_fmts[code->index]; - break; - - case IPIPE_PAD_SOURCE_VP: - /* FIXME: Forced format conversion inside IPIPE ? */ - if (code->index != 0) - return -EINVAL; - - code->code = MEDIA_BUS_FMT_UYVY8_1X16; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int ipipe_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt format; - - if (fse->index != 0) - return -EINVAL; - - format.code = fse->code; - format.width = 1; - format.height = 1; - ipipe_try_format(ipipe, sd_state, fse->pad, &format, fse->which); - fse->min_width = format.width; - fse->min_height = format.height; - - if (format.code != fse->code) - return -EINVAL; - - format.code = fse->code; - format.width = -1; - format.height = -1; - ipipe_try_format(ipipe, sd_state, fse->pad, &format, fse->which); - fse->max_width = format.width; - fse->max_height = format.height; - - return 0; -} - -/* - * ipipe_get_format - Retrieve the video format on a pad - * @sd : ISP IPIPE V4L2 subdevice - * @sd_state: V4L2 subdev state - * @fmt: Format - * - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond - * to the format type. - */ -static int ipipe_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __ipipe_get_format(ipipe, sd_state, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - fmt->format = *format; - return 0; -} - -/* - * ipipe_set_format - Set the video format on a pad - * @sd : ISP IPIPE V4L2 subdevice - * @sd_state: V4L2 subdev state - * @fmt: Format - * - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond - * to the format type. - */ -static int ipipe_set_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __ipipe_get_format(ipipe, sd_state, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - ipipe_try_format(ipipe, sd_state, fmt->pad, &fmt->format, fmt->which); - *format = fmt->format; - - /* Propagate the format from sink to source */ - if (fmt->pad == IPIPE_PAD_SINK) { - format = __ipipe_get_format(ipipe, sd_state, - IPIPE_PAD_SOURCE_VP, - fmt->which); - *format = fmt->format; - ipipe_try_format(ipipe, sd_state, IPIPE_PAD_SOURCE_VP, format, - fmt->which); - } - - return 0; -} - -static int ipipe_link_validate(struct v4l2_subdev *sd, struct media_link *link, - struct v4l2_subdev_format *source_fmt, - struct v4l2_subdev_format *sink_fmt) -{ - /* Check if the two ends match */ - if (source_fmt->format.width != sink_fmt->format.width || - source_fmt->format.height != sink_fmt->format.height) - return -EPIPE; - - if (source_fmt->format.code != sink_fmt->format.code) - return -EPIPE; - - return 0; -} - -/* - * ipipe_init_formats - Initialize formats on all pads - * @sd: ISP IPIPE V4L2 subdevice - * @fh: V4L2 subdev file handle - * - * Initialize all pad formats with default values. If fh is not NULL, try - * formats are initialized on the file handle. Otherwise active formats are - * initialized on the device. - */ -static int ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - struct v4l2_subdev_format format; - - memset(&format, 0, sizeof(format)); - format.pad = IPIPE_PAD_SINK; - format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; - format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10; - format.format.width = 4096; - format.format.height = 4096; - ipipe_set_format(sd, fh ? fh->state : NULL, &format); - - return 0; -} - -/* V4L2 subdev video operations */ -static const struct v4l2_subdev_video_ops ipipe_v4l2_video_ops = { - .s_stream = ipipe_set_stream, -}; - -/* V4L2 subdev pad operations */ -static const struct v4l2_subdev_pad_ops ipipe_v4l2_pad_ops = { - .enum_mbus_code = ipipe_enum_mbus_code, - .enum_frame_size = ipipe_enum_frame_size, - .get_fmt = ipipe_get_format, - .set_fmt = ipipe_set_format, - .link_validate = ipipe_link_validate, -}; - -/* V4L2 subdev operations */ -static const struct v4l2_subdev_ops ipipe_v4l2_ops = { - .video = &ipipe_v4l2_video_ops, - .pad = &ipipe_v4l2_pad_ops, -}; - -/* V4L2 subdev internal operations */ -static const struct v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = { - .open = ipipe_init_formats, -}; - -/* ----------------------------------------------------------------------------- - * Media entity operations - */ - -/* - * ipipe_link_setup - Setup IPIPE connections - * @entity: IPIPE media entity - * @local: Pad at the local end of the link - * @remote: Pad at the remote end of the link - * @flags: Link flags - * - * return -EINVAL or zero on success - */ -static int ipipe_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct iss_device *iss = to_iss_device(ipipe); - - if (!is_media_entity_v4l2_subdev(remote->entity)) - return -EINVAL; - - switch (local->index) { - case IPIPE_PAD_SINK: - /* Read from IPIPEIF. */ - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ipipe->input = IPIPE_INPUT_NONE; - break; - } - - if (ipipe->input != IPIPE_INPUT_NONE) - return -EBUSY; - - if (remote->entity == &iss->ipipeif.subdev.entity) - ipipe->input = IPIPE_INPUT_IPIPEIF; - - break; - - case IPIPE_PAD_SOURCE_VP: - /* Send to RESIZER */ - if (flags & MEDIA_LNK_FL_ENABLED) { - if (ipipe->output & ~IPIPE_OUTPUT_VP) - return -EBUSY; - ipipe->output |= IPIPE_OUTPUT_VP; - } else { - ipipe->output &= ~IPIPE_OUTPUT_VP; - } - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* media operations */ -static const struct media_entity_operations ipipe_media_ops = { - .link_setup = ipipe_link_setup, - .link_validate = v4l2_subdev_link_validate, -}; - -/* - * ipipe_init_entities - Initialize V4L2 subdev and media entity - * @ipipe: ISS ISP IPIPE module - * - * Return 0 on success and a negative error code on failure. - */ -static int ipipe_init_entities(struct iss_ipipe_device *ipipe) -{ - struct v4l2_subdev *sd = &ipipe->subdev; - struct media_pad *pads = ipipe->pads; - struct media_entity *me = &sd->entity; - int ret; - - ipipe->input = IPIPE_INPUT_NONE; - - v4l2_subdev_init(sd, &ipipe_v4l2_ops); - sd->internal_ops = &ipipe_v4l2_internal_ops; - strscpy(sd->name, "OMAP4 ISS ISP IPIPE", sizeof(sd->name)); - sd->grp_id = BIT(16); /* group ID for iss subdevs */ - v4l2_set_subdevdata(sd, ipipe); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[IPIPE_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; - - me->ops = &ipipe_media_ops; - ret = media_entity_pads_init(me, IPIPE_PADS_NUM, pads); - if (ret < 0) - return ret; - - ipipe_init_formats(sd, NULL); - - return 0; -} - -void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe) -{ - v4l2_device_unregister_subdev(&ipipe->subdev); -} - -int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe, - struct v4l2_device *vdev) -{ - int ret; - - /* Register the subdev and video node. */ - ret = v4l2_device_register_subdev(vdev, &ipipe->subdev); - if (ret < 0) - goto error; - - return 0; - -error: - omap4iss_ipipe_unregister_entities(ipipe); - return ret; -} - -/* ----------------------------------------------------------------------------- - * ISP IPIPE initialisation and cleanup - */ - -/* - * omap4iss_ipipe_init - IPIPE module initialization. - * @iss: Device pointer specific to the OMAP4 ISS. - * - * TODO: Get the initialisation values from platform data. - * - * Return 0 on success or a negative error code otherwise. - */ -int omap4iss_ipipe_init(struct iss_device *iss) -{ - struct iss_ipipe_device *ipipe = &iss->ipipe; - - ipipe->state = ISS_PIPELINE_STREAM_STOPPED; - init_waitqueue_head(&ipipe->wait); - - return ipipe_init_entities(ipipe); -} - -/* - * omap4iss_ipipe_cleanup - IPIPE module cleanup. - * @iss: Device pointer specific to the OMAP4 ISS. - */ -void omap4iss_ipipe_cleanup(struct iss_device *iss) -{ - struct iss_ipipe_device *ipipe = &iss->ipipe; - - media_entity_cleanup(&ipipe->subdev.entity); -} diff --git a/drivers/staging/media/omap4iss/iss_ipipe.h b/drivers/staging/media/omap4iss/iss_ipipe.h deleted file mode 100644 index 53b42aac1696..000000000000 --- a/drivers/staging/media/omap4iss/iss_ipipe.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#ifndef OMAP4_ISS_IPIPE_H -#define OMAP4_ISS_IPIPE_H - -#include "iss_video.h" - -enum ipipe_input_entity { - IPIPE_INPUT_NONE, - IPIPE_INPUT_IPIPEIF, -}; - -#define IPIPE_OUTPUT_VP BIT(0) - -/* Sink and source IPIPE pads */ -#define IPIPE_PAD_SINK 0 -#define IPIPE_PAD_SOURCE_VP 1 -#define IPIPE_PADS_NUM 2 - -/* - * struct iss_ipipe_device - Structure for the IPIPE module to store its own - * information - * @subdev: V4L2 subdevice - * @pads: Sink and source media entity pads - * @formats: Active video formats - * @input: Active input - * @output: Active outputs - * @error: A hardware error occurred during capture - * @state: Streaming state - * @wait: Wait queue used to stop the module - * @stopping: Stopping state - */ -struct iss_ipipe_device { - struct v4l2_subdev subdev; - struct media_pad pads[IPIPE_PADS_NUM]; - struct v4l2_mbus_framefmt formats[IPIPE_PADS_NUM]; - - enum ipipe_input_entity input; - unsigned int output; - unsigned int error; - - enum iss_pipeline_stream_state state; - wait_queue_head_t wait; - atomic_t stopping; -}; - -struct iss_device; - -int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe, - struct v4l2_device *vdev); -void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe); - -int omap4iss_ipipe_init(struct iss_device *iss); -void omap4iss_ipipe_cleanup(struct iss_device *iss); - -#endif /* OMAP4_ISS_IPIPE_H */ diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c deleted file mode 100644 index 8fa99532d9d4..000000000000 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ /dev/null @@ -1,844 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "iss.h" -#include "iss_regs.h" -#include "iss_ipipeif.h" - -static const unsigned int ipipeif_fmts[] = { - MEDIA_BUS_FMT_SGRBG10_1X10, - MEDIA_BUS_FMT_SRGGB10_1X10, - MEDIA_BUS_FMT_SBGGR10_1X10, - MEDIA_BUS_FMT_SGBRG10_1X10, - MEDIA_BUS_FMT_UYVY8_1X16, - MEDIA_BUS_FMT_YUYV8_1X16, -}; - -/* - * ipipeif_print_status - Print current IPIPEIF Module register values. - * @ipipeif: Pointer to ISS ISP IPIPEIF device. - * - * Also prints other debug information stored in the IPIPEIF module. - */ -#define IPIPEIF_PRINT_REGISTER(iss, name)\ - dev_dbg(iss->dev, "###IPIPEIF " #name "=0x%08x\n", \ - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_##name)) - -#define ISIF_PRINT_REGISTER(iss, name)\ - dev_dbg(iss->dev, "###ISIF " #name "=0x%08x\n", \ - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_##name)) - -#define ISP5_PRINT_REGISTER(iss, name)\ - dev_dbg(iss->dev, "###ISP5 " #name "=0x%08x\n", \ - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_##name)) - -static void ipipeif_print_status(struct iss_ipipeif_device *ipipeif) -{ - struct iss_device *iss = to_iss_device(ipipeif); - - dev_dbg(iss->dev, "-------------IPIPEIF Register dump-------------\n"); - - IPIPEIF_PRINT_REGISTER(iss, CFG1); - IPIPEIF_PRINT_REGISTER(iss, CFG2); - - ISIF_PRINT_REGISTER(iss, SYNCEN); - ISIF_PRINT_REGISTER(iss, CADU); - ISIF_PRINT_REGISTER(iss, CADL); - ISIF_PRINT_REGISTER(iss, MODESET); - ISIF_PRINT_REGISTER(iss, CCOLP); - ISIF_PRINT_REGISTER(iss, SPH); - ISIF_PRINT_REGISTER(iss, LNH); - ISIF_PRINT_REGISTER(iss, LNV); - ISIF_PRINT_REGISTER(iss, VDINT(0)); - ISIF_PRINT_REGISTER(iss, HSIZE); - - ISP5_PRINT_REGISTER(iss, SYSCONFIG); - ISP5_PRINT_REGISTER(iss, CTRL); - ISP5_PRINT_REGISTER(iss, IRQSTATUS(0)); - ISP5_PRINT_REGISTER(iss, IRQENABLE_SET(0)); - ISP5_PRINT_REGISTER(iss, IRQENABLE_CLR(0)); - - dev_dbg(iss->dev, "-----------------------------------------------\n"); -} - -static void ipipeif_write_enable(struct iss_ipipeif_device *ipipeif, u8 enable) -{ - struct iss_device *iss = to_iss_device(ipipeif); - - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SYNCEN, - ISIF_SYNCEN_DWEN, enable ? ISIF_SYNCEN_DWEN : 0); -} - -/* - * ipipeif_enable - Enable/Disable IPIPEIF. - * @enable: enable flag - * - */ -static void ipipeif_enable(struct iss_ipipeif_device *ipipeif, u8 enable) -{ - struct iss_device *iss = to_iss_device(ipipeif); - - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SYNCEN, - ISIF_SYNCEN_SYEN, enable ? ISIF_SYNCEN_SYEN : 0); -} - -/* ----------------------------------------------------------------------------- - * Format- and pipeline-related configuration helpers - */ - -/* - * ipipeif_set_outaddr - Set memory address to save output image - * @ipipeif: Pointer to ISP IPIPEIF device. - * @addr: 32-bit memory address aligned on 32 byte boundary. - * - * Sets the memory address where the output will be saved. - */ -static void ipipeif_set_outaddr(struct iss_ipipeif_device *ipipeif, u32 addr) -{ - struct iss_device *iss = to_iss_device(ipipeif); - - /* Save address split in Base Address H & L */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CADU, - (addr >> (16 + 5)) & ISIF_CADU_MASK); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CADL, - (addr >> 5) & ISIF_CADL_MASK); -} - -static void ipipeif_configure(struct iss_ipipeif_device *ipipeif) -{ - struct iss_device *iss = to_iss_device(ipipeif); - const struct iss_format_info *info; - struct v4l2_mbus_framefmt *format; - u32 isif_ccolp = 0; - - omap4iss_configure_bridge(iss, ipipeif->input); - - /* IPIPEIF_PAD_SINK */ - format = &ipipeif->formats[IPIPEIF_PAD_SINK]; - - /* IPIPEIF with YUV422 input from ISIF */ - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG1, - IPIPEIF_CFG1_INPSRC1_MASK | IPIPEIF_CFG1_INPSRC2_MASK); - - /* Select ISIF/IPIPEIF input format */ - switch (format->code) { - case MEDIA_BUS_FMT_UYVY8_1X16: - case MEDIA_BUS_FMT_YUYV8_1X16: - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_MODESET, - ISIF_MODESET_CCDMD | ISIF_MODESET_INPMOD_MASK | - ISIF_MODESET_CCDW_MASK, - ISIF_MODESET_INPMOD_YCBCR16); - - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG2, - IPIPEIF_CFG2_YUV8, IPIPEIF_CFG2_YUV16); - - break; - case MEDIA_BUS_FMT_SGRBG10_1X10: - isif_ccolp = ISIF_CCOLP_CP0_F0_GR | - ISIF_CCOLP_CP1_F0_R | - ISIF_CCOLP_CP2_F0_B | - ISIF_CCOLP_CP3_F0_GB; - goto cont_raw; - case MEDIA_BUS_FMT_SRGGB10_1X10: - isif_ccolp = ISIF_CCOLP_CP0_F0_R | - ISIF_CCOLP_CP1_F0_GR | - ISIF_CCOLP_CP2_F0_GB | - ISIF_CCOLP_CP3_F0_B; - goto cont_raw; - case MEDIA_BUS_FMT_SBGGR10_1X10: - isif_ccolp = ISIF_CCOLP_CP0_F0_B | - ISIF_CCOLP_CP1_F0_GB | - ISIF_CCOLP_CP2_F0_GR | - ISIF_CCOLP_CP3_F0_R; - goto cont_raw; - case MEDIA_BUS_FMT_SGBRG10_1X10: - isif_ccolp = ISIF_CCOLP_CP0_F0_GB | - ISIF_CCOLP_CP1_F0_B | - ISIF_CCOLP_CP2_F0_R | - ISIF_CCOLP_CP3_F0_GR; -cont_raw: - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG2, - IPIPEIF_CFG2_YUV16); - - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_MODESET, - ISIF_MODESET_CCDMD | ISIF_MODESET_INPMOD_MASK | - ISIF_MODESET_CCDW_MASK, ISIF_MODESET_INPMOD_RAW | - ISIF_MODESET_CCDW_2BIT); - - info = omap4iss_video_format_info(format->code); - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CGAMMAWD, - ISIF_CGAMMAWD_GWDI_MASK, - ISIF_CGAMMAWD_GWDI(info->bpp)); - - /* Set RAW Bayer pattern */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CCOLP, - isif_ccolp); - break; - } - - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SPH, 0 & ISIF_SPH_MASK); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_LNH, - (format->width - 1) & ISIF_LNH_MASK); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_LNV, - (format->height - 1) & ISIF_LNV_MASK); - - /* Generate ISIF0 on the last line of the image */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_VDINT(0), - format->height - 1); - - /* IPIPEIF_PAD_SOURCE_ISIF_SF */ - format = &ipipeif->formats[IPIPEIF_PAD_SOURCE_ISIF_SF]; - - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_HSIZE, - (ipipeif->video_out.bpl_value >> 5) & - ISIF_HSIZE_HSIZE_MASK); - - /* IPIPEIF_PAD_SOURCE_VP */ - /* Do nothing? */ -} - -/* ----------------------------------------------------------------------------- - * Interrupt handling - */ - -static void ipipeif_isr_buffer(struct iss_ipipeif_device *ipipeif) -{ - struct iss_buffer *buffer; - - /* The ISIF generates VD0 interrupts even when writes are disabled. - * deal with it anyway). Disabling the ISIF when no buffer is available - * is thus not be enough, we need to handle the situation explicitly. - */ - if (list_empty(&ipipeif->video_out.dmaqueue)) - return; - - ipipeif_write_enable(ipipeif, 0); - - buffer = omap4iss_video_buffer_next(&ipipeif->video_out); - if (!buffer) - return; - - ipipeif_set_outaddr(ipipeif, buffer->iss_addr); - - ipipeif_write_enable(ipipeif, 1); -} - -/* - * omap4iss_ipipeif_isr - Configure ipipeif during interframe time. - * @ipipeif: Pointer to ISP IPIPEIF device. - * @events: IPIPEIF events - */ -void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events) -{ - if (omap4iss_module_sync_is_stopping(&ipipeif->wait, - &ipipeif->stopping)) - return; - - if ((events & ISP5_IRQ_ISIF_INT(0)) && - (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)) - ipipeif_isr_buffer(ipipeif); -} - -/* ----------------------------------------------------------------------------- - * ISP video operations - */ - -static int ipipeif_video_queue(struct iss_video *video, - struct iss_buffer *buffer) -{ - struct iss_ipipeif_device *ipipeif = container_of(video, - struct iss_ipipeif_device, video_out); - - if (!(ipipeif->output & IPIPEIF_OUTPUT_MEMORY)) - return -ENODEV; - - ipipeif_set_outaddr(ipipeif, buffer->iss_addr); - - /* - * If streaming was enabled before there was a buffer queued - * or underrun happened in the ISR, the hardware was not enabled - * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set. - * Enable it now. - */ - if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { - if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) - ipipeif_write_enable(ipipeif, 1); - ipipeif_enable(ipipeif, 1); - iss_video_dmaqueue_flags_clr(video); - } - - return 0; -} - -static const struct iss_video_operations ipipeif_video_ops = { - .queue = ipipeif_video_queue, -}; - -/* ----------------------------------------------------------------------------- - * V4L2 subdev operations - */ - -#define IPIPEIF_DRV_SUBCLK_MASK (OMAP4_ISS_ISP_SUBCLK_IPIPEIF |\ - OMAP4_ISS_ISP_SUBCLK_ISIF) -/* - * ipipeif_set_stream - Enable/Disable streaming on the IPIPEIF module - * @sd: ISP IPIPEIF V4L2 subdevice - * @enable: Enable/disable stream - */ -static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct iss_device *iss = to_iss_device(ipipeif); - struct iss_video *video_out = &ipipeif->video_out; - int ret = 0; - - if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED) { - if (enable == ISS_PIPELINE_STREAM_STOPPED) - return 0; - - omap4iss_isp_subclk_enable(iss, IPIPEIF_DRV_SUBCLK_MASK); - } - - switch (enable) { - case ISS_PIPELINE_STREAM_CONTINUOUS: - - ipipeif_configure(ipipeif); - ipipeif_print_status(ipipeif); - - /* - * When outputting to memory with no buffer available, let the - * buffer queue handler start the hardware. A DMA queue flag - * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is - * a buffer available. - */ - if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY && - !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED)) - break; - - atomic_set(&ipipeif->stopping, 0); - if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) - ipipeif_write_enable(ipipeif, 1); - ipipeif_enable(ipipeif, 1); - iss_video_dmaqueue_flags_clr(video_out); - break; - - case ISS_PIPELINE_STREAM_STOPPED: - if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED) - return 0; - if (omap4iss_module_sync_idle(&sd->entity, &ipipeif->wait, - &ipipeif->stopping)) - ret = -ETIMEDOUT; - - if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) - ipipeif_write_enable(ipipeif, 0); - ipipeif_enable(ipipeif, 0); - omap4iss_isp_subclk_disable(iss, IPIPEIF_DRV_SUBCLK_MASK); - iss_video_dmaqueue_flags_clr(video_out); - break; - } - - ipipeif->state = enable; - return ret; -} - -static struct v4l2_mbus_framefmt * -__ipipeif_get_format(struct iss_ipipeif_device *ipipeif, - struct v4l2_subdev_state *sd_state, unsigned int pad, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_state_get_format(sd_state, pad); - return &ipipeif->formats[pad]; -} - -/* - * ipipeif_try_format - Try video format on a pad - * @ipipeif: ISS IPIPEIF device - * @sd_state: V4L2 subdev state - * @pad: Pad number - * @fmt: Format - */ -static void -ipipeif_try_format(struct iss_ipipeif_device *ipipeif, - struct v4l2_subdev_state *sd_state, unsigned int pad, - struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) -{ - struct v4l2_mbus_framefmt *format; - unsigned int width = fmt->width; - unsigned int height = fmt->height; - unsigned int i; - - switch (pad) { - case IPIPEIF_PAD_SINK: - /* TODO: If the IPIPEIF output formatter pad is connected - * directly to the resizer, only YUV formats can be used. - */ - for (i = 0; i < ARRAY_SIZE(ipipeif_fmts); i++) { - if (fmt->code == ipipeif_fmts[i]) - break; - } - - /* If not found, use SGRBG10 as default */ - if (i >= ARRAY_SIZE(ipipeif_fmts)) - fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; - - /* Clamp the input size. */ - fmt->width = clamp_t(u32, width, 1, 8192); - fmt->height = clamp_t(u32, height, 1, 8192); - break; - - case IPIPEIF_PAD_SOURCE_ISIF_SF: - format = __ipipeif_get_format(ipipeif, sd_state, - IPIPEIF_PAD_SINK, - which); - memcpy(fmt, format, sizeof(*fmt)); - - /* The data formatter truncates the number of horizontal output - * pixels to a multiple of 16. To avoid clipping data, allow - * callers to request an output size bigger than the input size - * up to the nearest multiple of 16. - */ - fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15); - fmt->width &= ~15; - fmt->height = clamp_t(u32, height, 32, fmt->height); - break; - - case IPIPEIF_PAD_SOURCE_VP: - format = __ipipeif_get_format(ipipeif, sd_state, - IPIPEIF_PAD_SINK, - which); - memcpy(fmt, format, sizeof(*fmt)); - - fmt->width = clamp_t(u32, width, 32, fmt->width); - fmt->height = clamp_t(u32, height, 32, fmt->height); - break; - } - - /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is - * stored on 2 bytes. - */ - fmt->colorspace = V4L2_COLORSPACE_SRGB; - fmt->field = V4L2_FIELD_NONE; -} - -/* - * ipipeif_enum_mbus_code - Handle pixel format enumeration - * @sd : pointer to v4l2 subdev structure - * @sd_state: V4L2 subdev state - * @code : pointer to v4l2_subdev_mbus_code_enum structure - * return -EINVAL or zero on success - */ -static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - switch (code->pad) { - case IPIPEIF_PAD_SINK: - if (code->index >= ARRAY_SIZE(ipipeif_fmts)) - return -EINVAL; - - code->code = ipipeif_fmts[code->index]; - break; - - case IPIPEIF_PAD_SOURCE_ISIF_SF: - case IPIPEIF_PAD_SOURCE_VP: - /* No format conversion inside IPIPEIF */ - if (code->index != 0) - return -EINVAL; - - format = __ipipeif_get_format(ipipeif, sd_state, - IPIPEIF_PAD_SINK, - code->which); - - code->code = format->code; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int ipipeif_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt format; - - if (fse->index != 0) - return -EINVAL; - - format.code = fse->code; - format.width = 1; - format.height = 1; - ipipeif_try_format(ipipeif, sd_state, fse->pad, &format, fse->which); - fse->min_width = format.width; - fse->min_height = format.height; - - if (format.code != fse->code) - return -EINVAL; - - format.code = fse->code; - format.width = -1; - format.height = -1; - ipipeif_try_format(ipipeif, sd_state, fse->pad, &format, fse->which); - fse->max_width = format.width; - fse->max_height = format.height; - - return 0; -} - -/* - * ipipeif_get_format - Retrieve the video format on a pad - * @sd : ISP IPIPEIF V4L2 subdevice - * @sd_state: V4L2 subdev state - * @fmt: Format - * - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond - * to the format type. - */ -static int ipipeif_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __ipipeif_get_format(ipipeif, sd_state, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - fmt->format = *format; - return 0; -} - -/* - * ipipeif_set_format - Set the video format on a pad - * @sd : ISP IPIPEIF V4L2 subdevice - * @sd_state: V4L2 subdev state - * @fmt: Format - * - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond - * to the format type. - */ -static int ipipeif_set_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __ipipeif_get_format(ipipeif, sd_state, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - ipipeif_try_format(ipipeif, sd_state, fmt->pad, &fmt->format, - fmt->which); - *format = fmt->format; - - /* Propagate the format from sink to source */ - if (fmt->pad == IPIPEIF_PAD_SINK) { - format = __ipipeif_get_format(ipipeif, sd_state, - IPIPEIF_PAD_SOURCE_ISIF_SF, - fmt->which); - *format = fmt->format; - ipipeif_try_format(ipipeif, sd_state, - IPIPEIF_PAD_SOURCE_ISIF_SF, - format, fmt->which); - - format = __ipipeif_get_format(ipipeif, sd_state, - IPIPEIF_PAD_SOURCE_VP, - fmt->which); - *format = fmt->format; - ipipeif_try_format(ipipeif, sd_state, IPIPEIF_PAD_SOURCE_VP, - format, - fmt->which); - } - - return 0; -} - -static int ipipeif_link_validate(struct v4l2_subdev *sd, - struct media_link *link, - struct v4l2_subdev_format *source_fmt, - struct v4l2_subdev_format *sink_fmt) -{ - /* Check if the two ends match */ - if (source_fmt->format.width != sink_fmt->format.width || - source_fmt->format.height != sink_fmt->format.height) - return -EPIPE; - - if (source_fmt->format.code != sink_fmt->format.code) - return -EPIPE; - - return 0; -} - -/* - * ipipeif_init_formats - Initialize formats on all pads - * @sd: ISP IPIPEIF V4L2 subdevice - * @fh: V4L2 subdev file handle - * - * Initialize all pad formats with default values. If fh is not NULL, try - * formats are initialized on the file handle. Otherwise active formats are - * initialized on the device. - */ -static int ipipeif_init_formats(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct v4l2_subdev_format format; - - memset(&format, 0, sizeof(format)); - format.pad = IPIPEIF_PAD_SINK; - format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; - format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10; - format.format.width = 4096; - format.format.height = 4096; - ipipeif_set_format(sd, fh ? fh->state : NULL, &format); - - return 0; -} - -/* V4L2 subdev video operations */ -static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = { - .s_stream = ipipeif_set_stream, -}; - -/* V4L2 subdev pad operations */ -static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = { - .enum_mbus_code = ipipeif_enum_mbus_code, - .enum_frame_size = ipipeif_enum_frame_size, - .get_fmt = ipipeif_get_format, - .set_fmt = ipipeif_set_format, - .link_validate = ipipeif_link_validate, -}; - -/* V4L2 subdev operations */ -static const struct v4l2_subdev_ops ipipeif_v4l2_ops = { - .video = &ipipeif_v4l2_video_ops, - .pad = &ipipeif_v4l2_pad_ops, -}; - -/* V4L2 subdev internal operations */ -static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = { - .open = ipipeif_init_formats, -}; - -/* ----------------------------------------------------------------------------- - * Media entity operations - */ - -/* - * ipipeif_link_setup - Setup IPIPEIF connections - * @entity: IPIPEIF media entity - * @local: Pad at the local end of the link - * @remote: Pad at the remote end of the link - * @flags: Link flags - * - * return -EINVAL or zero on success - */ -static int ipipeif_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct iss_device *iss = to_iss_device(ipipeif); - unsigned int index = local->index; - - /* FIXME: this is actually a hack! */ - if (is_media_entity_v4l2_subdev(remote->entity)) - index |= 2 << 16; - - switch (index) { - case IPIPEIF_PAD_SINK | 2 << 16: - /* Read from the sensor CSI2a or CSI2b. */ - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ipipeif->input = IPIPEIF_INPUT_NONE; - break; - } - - if (ipipeif->input != IPIPEIF_INPUT_NONE) - return -EBUSY; - - if (remote->entity == &iss->csi2a.subdev.entity) - ipipeif->input = IPIPEIF_INPUT_CSI2A; - else if (remote->entity == &iss->csi2b.subdev.entity) - ipipeif->input = IPIPEIF_INPUT_CSI2B; - - break; - - case IPIPEIF_PAD_SOURCE_ISIF_SF: - /* Write to memory */ - if (flags & MEDIA_LNK_FL_ENABLED) { - if (ipipeif->output & ~IPIPEIF_OUTPUT_MEMORY) - return -EBUSY; - ipipeif->output |= IPIPEIF_OUTPUT_MEMORY; - } else { - ipipeif->output &= ~IPIPEIF_OUTPUT_MEMORY; - } - break; - - case IPIPEIF_PAD_SOURCE_VP | 2 << 16: - /* Send to IPIPE/RESIZER */ - if (flags & MEDIA_LNK_FL_ENABLED) { - if (ipipeif->output & ~IPIPEIF_OUTPUT_VP) - return -EBUSY; - ipipeif->output |= IPIPEIF_OUTPUT_VP; - } else { - ipipeif->output &= ~IPIPEIF_OUTPUT_VP; - } - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* media operations */ -static const struct media_entity_operations ipipeif_media_ops = { - .link_setup = ipipeif_link_setup, - .link_validate = v4l2_subdev_link_validate, -}; - -/* - * ipipeif_init_entities - Initialize V4L2 subdev and media entity - * @ipipeif: ISS ISP IPIPEIF module - * - * Return 0 on success and a negative error code on failure. - */ -static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif) -{ - struct v4l2_subdev *sd = &ipipeif->subdev; - struct media_pad *pads = ipipeif->pads; - struct media_entity *me = &sd->entity; - int ret; - - ipipeif->input = IPIPEIF_INPUT_NONE; - - v4l2_subdev_init(sd, &ipipeif_v4l2_ops); - sd->internal_ops = &ipipeif_v4l2_internal_ops; - strscpy(sd->name, "OMAP4 ISS ISP IPIPEIF", sizeof(sd->name)); - sd->grp_id = BIT(16); /* group ID for iss subdevs */ - v4l2_set_subdevdata(sd, ipipeif); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[IPIPEIF_PAD_SOURCE_ISIF_SF].flags = MEDIA_PAD_FL_SOURCE; - pads[IPIPEIF_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; - - me->ops = &ipipeif_media_ops; - ret = media_entity_pads_init(me, IPIPEIF_PADS_NUM, pads); - if (ret < 0) - return ret; - - ipipeif_init_formats(sd, NULL); - - ipipeif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - ipipeif->video_out.ops = &ipipeif_video_ops; - ipipeif->video_out.iss = to_iss_device(ipipeif); - ipipeif->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; - ipipeif->video_out.bpl_alignment = 32; - ipipeif->video_out.bpl_zero_padding = 1; - ipipeif->video_out.bpl_max = 0x1ffe0; - - return omap4iss_video_init(&ipipeif->video_out, "ISP IPIPEIF"); -} - -void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif) -{ - v4l2_device_unregister_subdev(&ipipeif->subdev); - omap4iss_video_unregister(&ipipeif->video_out); -} - -int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif, - struct v4l2_device *vdev) -{ - int ret; - - /* Register the subdev and video node. */ - ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev); - if (ret < 0) - goto error; - - ret = omap4iss_video_register(&ipipeif->video_out, vdev); - if (ret < 0) - goto error; - - return 0; - -error: - omap4iss_ipipeif_unregister_entities(ipipeif); - return ret; -} - -/* ----------------------------------------------------------------------------- - * ISP IPIPEIF initialisation and cleanup - */ - -/* - * omap4iss_ipipeif_init - IPIPEIF module initialization. - * @iss: Device pointer specific to the OMAP4 ISS. - * - * TODO: Get the initialisation values from platform data. - * - * Return 0 on success or a negative error code otherwise. - */ -int omap4iss_ipipeif_init(struct iss_device *iss) -{ - struct iss_ipipeif_device *ipipeif = &iss->ipipeif; - - ipipeif->state = ISS_PIPELINE_STREAM_STOPPED; - init_waitqueue_head(&ipipeif->wait); - - return ipipeif_init_entities(ipipeif); -} - -/* - * omap4iss_ipipeif_create_links() - IPIPEIF pads links creation - * @iss: Pointer to ISS device - * - * return negative error code or zero on success - */ -int omap4iss_ipipeif_create_links(struct iss_device *iss) -{ - struct iss_ipipeif_device *ipipeif = &iss->ipipeif; - - /* Connect the IPIPEIF subdev to the video node. */ - return media_create_pad_link(&ipipeif->subdev.entity, - IPIPEIF_PAD_SOURCE_ISIF_SF, - &ipipeif->video_out.video.entity, 0, 0); -} - -/* - * omap4iss_ipipeif_cleanup - IPIPEIF module cleanup. - * @iss: Device pointer specific to the OMAP4 ISS. - */ -void omap4iss_ipipeif_cleanup(struct iss_device *iss) -{ - struct iss_ipipeif_device *ipipeif = &iss->ipipeif; - - media_entity_cleanup(&ipipeif->subdev.entity); -} diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.h b/drivers/staging/media/omap4iss/iss_ipipeif.h deleted file mode 100644 index 69792333a62e..000000000000 --- a/drivers/staging/media/omap4iss/iss_ipipeif.h +++ /dev/null @@ -1,89 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#ifndef OMAP4_ISS_IPIPEIF_H -#define OMAP4_ISS_IPIPEIF_H - -#include "iss_video.h" - -enum ipipeif_input_entity { - IPIPEIF_INPUT_NONE, - IPIPEIF_INPUT_CSI2A, - IPIPEIF_INPUT_CSI2B -}; - -#define IPIPEIF_OUTPUT_MEMORY BIT(0) -#define IPIPEIF_OUTPUT_VP BIT(1) - -/* Sink and source IPIPEIF pads */ -#define IPIPEIF_PAD_SINK 0 -#define IPIPEIF_PAD_SOURCE_ISIF_SF 1 -#define IPIPEIF_PAD_SOURCE_VP 2 -#define IPIPEIF_PADS_NUM 3 - -/* - * struct iss_ipipeif_device - Structure for the IPIPEIF module to store its own - * information - * @subdev: V4L2 subdevice - * @pads: Sink and source media entity pads - * @formats: Active video formats - * @input: Active input - * @output: Active outputs - * @video_out: Output video node - * @error: A hardware error occurred during capture - * @alaw: A-law compression enabled (1) or disabled (0) - * @lpf: Low pass filter enabled (1) or disabled (0) - * @obclamp: Optical-black clamp enabled (1) or disabled (0) - * @fpc_en: Faulty pixels correction enabled (1) or disabled (0) - * @blcomp: Black level compensation configuration - * @clamp: Optical-black or digital clamp configuration - * @fpc: Faulty pixels correction configuration - * @lsc: Lens shading compensation configuration - * @update: Bitmask of controls to update during the next interrupt - * @shadow_update: Controls update in progress by userspace - * @syncif: Interface synchronization configuration - * @vpcfg: Video port configuration - * @underrun: A buffer underrun occurred and a new buffer has been queued - * @state: Streaming state - * @lock: Serializes shadow_update with interrupt handler - * @wait: Wait queue used to stop the module - * @stopping: Stopping state - * @ioctl_lock: Serializes ioctl calls and LSC requests freeing - */ -struct iss_ipipeif_device { - struct v4l2_subdev subdev; - struct media_pad pads[IPIPEIF_PADS_NUM]; - struct v4l2_mbus_framefmt formats[IPIPEIF_PADS_NUM]; - - enum ipipeif_input_entity input; - unsigned int output; - struct iss_video video_out; - unsigned int error; - - enum iss_pipeline_stream_state state; - wait_queue_head_t wait; - atomic_t stopping; -}; - -struct iss_device; - -int omap4iss_ipipeif_init(struct iss_device *iss); -int omap4iss_ipipeif_create_links(struct iss_device *iss); -void omap4iss_ipipeif_cleanup(struct iss_device *iss); -int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif, - struct v4l2_device *vdev); -void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif); - -int omap4iss_ipipeif_busy(struct iss_ipipeif_device *ipipeif); -void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events); -void omap4iss_ipipeif_restore_context(struct iss_device *iss); -void omap4iss_ipipeif_max_rate(struct iss_ipipeif_device *ipipeif, - unsigned int *max_rate); - -#endif /* OMAP4_ISS_IPIPEIF_H */ diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h deleted file mode 100644 index cfe0bb075072..000000000000 --- a/drivers/staging/media/omap4iss/iss_regs.h +++ /dev/null @@ -1,899 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * TI OMAP4 ISS V4L2 Driver - Register defines - * - * Copyright (C) 2012 Texas Instruments. - * - * Author: Sergio Aguirre - */ - -#ifndef _OMAP4_ISS_REGS_H_ -#define _OMAP4_ISS_REGS_H_ - -/* ISS */ -#define ISS_HL_REVISION 0x0 - -#define ISS_HL_SYSCONFIG 0x10 -#define ISS_HL_SYSCONFIG_IDLEMODE_SHIFT 2 -#define ISS_HL_SYSCONFIG_IDLEMODE_FORCEIDLE 0x0 -#define ISS_HL_SYSCONFIG_IDLEMODE_NOIDLE 0x1 -#define ISS_HL_SYSCONFIG_IDLEMODE_SMARTIDLE 0x2 -#define ISS_HL_SYSCONFIG_SOFTRESET BIT(0) - -#define ISS_HL_IRQSTATUS_RAW(i) (0x20 + (0x10 * (i))) -#define ISS_HL_IRQSTATUS(i) (0x24 + (0x10 * (i))) -#define ISS_HL_IRQENABLE_SET(i) (0x28 + (0x10 * (i))) -#define ISS_HL_IRQENABLE_CLR(i) (0x2c + (0x10 * (i))) - -#define ISS_HL_IRQ_HS_VS BIT(17) -#define ISS_HL_IRQ_SIMCOP(i) BIT(12 + (i)) -#define ISS_HL_IRQ_BTE BIT(11) -#define ISS_HL_IRQ_CBUFF BIT(10) -#define ISS_HL_IRQ_CCP2(i) BIT((i) > 3 ? 16 : 14 + (i)) -#define ISS_HL_IRQ_CSIB BIT(5) -#define ISS_HL_IRQ_CSIA BIT(4) -#define ISS_HL_IRQ_ISP(i) BIT(i) - -#define ISS_CTRL 0x80 -#define ISS_CTRL_CLK_DIV_MASK (3 << 4) -#define ISS_CTRL_INPUT_SEL_MASK (3 << 2) -#define ISS_CTRL_INPUT_SEL_CSI2A (0 << 2) -#define ISS_CTRL_INPUT_SEL_CSI2B (1 << 2) -#define ISS_CTRL_SYNC_DETECT_VS_RAISING (3 << 0) - -#define ISS_CLKCTRL 0x84 -#define ISS_CLKCTRL_VPORT2_CLK BIT(30) -#define ISS_CLKCTRL_VPORT1_CLK BIT(29) -#define ISS_CLKCTRL_VPORT0_CLK BIT(28) -#define ISS_CLKCTRL_CCP2 BIT(4) -#define ISS_CLKCTRL_CSI2_B BIT(3) -#define ISS_CLKCTRL_CSI2_A BIT(2) -#define ISS_CLKCTRL_ISP BIT(1) -#define ISS_CLKCTRL_SIMCOP BIT(0) - -#define ISS_CLKSTAT 0x88 -#define ISS_CLKSTAT_VPORT2_CLK BIT(30) -#define ISS_CLKSTAT_VPORT1_CLK BIT(29) -#define ISS_CLKSTAT_VPORT0_CLK BIT(28) -#define ISS_CLKSTAT_CCP2 BIT(4) -#define ISS_CLKSTAT_CSI2_B BIT(3) -#define ISS_CLKSTAT_CSI2_A BIT(2) -#define ISS_CLKSTAT_ISP BIT(1) -#define ISS_CLKSTAT_SIMCOP BIT(0) - -#define ISS_PM_STATUS 0x8c -#define ISS_PM_STATUS_CBUFF_PM_MASK (3 << 12) -#define ISS_PM_STATUS_BTE_PM_MASK (3 << 10) -#define ISS_PM_STATUS_SIMCOP_PM_MASK (3 << 8) -#define ISS_PM_STATUS_ISP_PM_MASK (3 << 6) -#define ISS_PM_STATUS_CCP2_PM_MASK (3 << 4) -#define ISS_PM_STATUS_CSI2_B_PM_MASK (3 << 2) -#define ISS_PM_STATUS_CSI2_A_PM_MASK (3 << 0) - -#define REGISTER0 0x0 -#define REGISTER0_HSCLOCKCONFIG BIT(24) -#define REGISTER0_THS_TERM_MASK (0xff << 8) -#define REGISTER0_THS_TERM_SHIFT 8 -#define REGISTER0_THS_SETTLE_MASK (0xff << 0) -#define REGISTER0_THS_SETTLE_SHIFT 0 - -#define REGISTER1 0x4 -#define REGISTER1_RESET_DONE_CTRLCLK BIT(29) -#define REGISTER1_CLOCK_MISS_DETECTOR_STATUS BIT(25) -#define REGISTER1_TCLK_TERM_MASK (0x3f << 18) -#define REGISTER1_TCLK_TERM_SHIFT 18 -#define REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT 10 -#define REGISTER1_CTRLCLK_DIV_FACTOR_MASK (0x3 << 8) -#define REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT 8 -#define REGISTER1_TCLK_SETTLE_MASK (0xff << 0) -#define REGISTER1_TCLK_SETTLE_SHIFT 0 - -#define REGISTER2 0x8 - -#define CSI2_SYSCONFIG 0x10 -#define CSI2_SYSCONFIG_MSTANDBY_MODE_MASK (3 << 12) -#define CSI2_SYSCONFIG_MSTANDBY_MODE_FORCE (0 << 12) -#define CSI2_SYSCONFIG_MSTANDBY_MODE_NO (1 << 12) -#define CSI2_SYSCONFIG_MSTANDBY_MODE_SMART (2 << 12) -#define CSI2_SYSCONFIG_SOFT_RESET (1 << 1) -#define CSI2_SYSCONFIG_AUTO_IDLE (1 << 0) - -#define CSI2_SYSSTATUS 0x14 -#define CSI2_SYSSTATUS_RESET_DONE BIT(0) - -#define CSI2_IRQSTATUS 0x18 -#define CSI2_IRQENABLE 0x1c - -/* Shared bits across CSI2_IRQENABLE and IRQSTATUS */ - -#define CSI2_IRQ_OCP_ERR BIT(14) -#define CSI2_IRQ_SHORT_PACKET BIT(13) -#define CSI2_IRQ_ECC_CORRECTION BIT(12) -#define CSI2_IRQ_ECC_NO_CORRECTION BIT(11) -#define CSI2_IRQ_COMPLEXIO_ERR BIT(9) -#define CSI2_IRQ_FIFO_OVF BIT(8) -#define CSI2_IRQ_CONTEXT0 BIT(0) - -#define CSI2_CTRL 0x40 -#define CSI2_CTRL_MFLAG_LEVH_MASK (7 << 20) -#define CSI2_CTRL_MFLAG_LEVH_SHIFT 20 -#define CSI2_CTRL_MFLAG_LEVL_MASK (7 << 17) -#define CSI2_CTRL_MFLAG_LEVL_SHIFT 17 -#define CSI2_CTRL_BURST_SIZE_EXPAND (1 << 16) -#define CSI2_CTRL_VP_CLK_EN (1 << 15) -#define CSI2_CTRL_NON_POSTED_WRITE (1 << 13) -#define CSI2_CTRL_VP_ONLY_EN (1 << 11) -#define CSI2_CTRL_VP_OUT_CTRL_MASK (3 << 8) -#define CSI2_CTRL_VP_OUT_CTRL_SHIFT 8 -#define CSI2_CTRL_DBG_EN (1 << 7) -#define CSI2_CTRL_BURST_SIZE_MASK (3 << 5) -#define CSI2_CTRL_ENDIANNESS (1 << 4) -#define CSI2_CTRL_FRAME (1 << 3) -#define CSI2_CTRL_ECC_EN (1 << 2) -#define CSI2_CTRL_IF_EN (1 << 0) - -#define CSI2_DBG_H 0x44 - -#define CSI2_COMPLEXIO_CFG 0x50 -#define CSI2_COMPLEXIO_CFG_RESET_CTRL (1 << 30) -#define CSI2_COMPLEXIO_CFG_RESET_DONE (1 << 29) -#define CSI2_COMPLEXIO_CFG_PWD_CMD_MASK (3 << 27) -#define CSI2_COMPLEXIO_CFG_PWD_CMD_OFF (0 << 27) -#define CSI2_COMPLEXIO_CFG_PWD_CMD_ON (1 << 27) -#define CSI2_COMPLEXIO_CFG_PWD_CMD_ULP (2 << 27) -#define CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK (3 << 25) -#define CSI2_COMPLEXIO_CFG_PWD_STATUS_OFF (0 << 25) -#define CSI2_COMPLEXIO_CFG_PWD_STATUS_ON (1 << 25) -#define CSI2_COMPLEXIO_CFG_PWD_STATUS_ULP (2 << 25) -#define CSI2_COMPLEXIO_CFG_PWR_AUTO (1 << 24) -#define CSI2_COMPLEXIO_CFG_DATA_POL(i) (1 << (((i) * 4) + 3)) -#define CSI2_COMPLEXIO_CFG_DATA_POSITION_MASK(i) (7 << ((i) * 4)) -#define CSI2_COMPLEXIO_CFG_DATA_POSITION_SHIFT(i) ((i) * 4) -#define CSI2_COMPLEXIO_CFG_CLOCK_POL (1 << 3) -#define CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK (7 << 0) -#define CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT 0 - -#define CSI2_COMPLEXIO_IRQSTATUS 0x54 - -#define CSI2_SHORT_PACKET 0x5c - -#define CSI2_COMPLEXIO_IRQENABLE 0x60 - -/* Shared bits across CSI2_COMPLEXIO_IRQENABLE and IRQSTATUS */ -#define CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT BIT(26) -#define CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER BIT(25) -#define CSI2_COMPLEXIO_IRQ_STATEULPM5 BIT(24) -#define CSI2_COMPLEXIO_IRQ_STATEULPM4 BIT(23) -#define CSI2_COMPLEXIO_IRQ_STATEULPM3 BIT(22) -#define CSI2_COMPLEXIO_IRQ_STATEULPM2 BIT(21) -#define CSI2_COMPLEXIO_IRQ_STATEULPM1 BIT(20) -#define CSI2_COMPLEXIO_IRQ_ERRCONTROL5 BIT(19) -#define CSI2_COMPLEXIO_IRQ_ERRCONTROL4 BIT(18) -#define CSI2_COMPLEXIO_IRQ_ERRCONTROL3 BIT(17) -#define CSI2_COMPLEXIO_IRQ_ERRCONTROL2 BIT(16) -#define CSI2_COMPLEXIO_IRQ_ERRCONTROL1 BIT(15) -#define CSI2_COMPLEXIO_IRQ_ERRESC5 BIT(14) -#define CSI2_COMPLEXIO_IRQ_ERRESC4 BIT(13) -#define CSI2_COMPLEXIO_IRQ_ERRESC3 BIT(12) -#define CSI2_COMPLEXIO_IRQ_ERRESC2 BIT(11) -#define CSI2_COMPLEXIO_IRQ_ERRESC1 BIT(10) -#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 BIT(9) -#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 BIT(8) -#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 BIT(7) -#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 BIT(6) -#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 BIT(5) -#define CSI2_COMPLEXIO_IRQ_ERRSOTHS5 BIT(4) -#define CSI2_COMPLEXIO_IRQ_ERRSOTHS4 BIT(3) -#define CSI2_COMPLEXIO_IRQ_ERRSOTHS3 BIT(2) -#define CSI2_COMPLEXIO_IRQ_ERRSOTHS2 BIT(1) -#define CSI2_COMPLEXIO_IRQ_ERRSOTHS1 BIT(0) - -#define CSI2_DBG_P 0x68 - -#define CSI2_TIMING 0x6c -#define CSI2_TIMING_FORCE_RX_MODE_IO1 BIT(15) -#define CSI2_TIMING_STOP_STATE_X16_IO1 BIT(14) -#define CSI2_TIMING_STOP_STATE_X4_IO1 BIT(13) -#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK (0x1fff << 0) -#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT 0 - -#define CSI2_CTX_CTRL1(i) (0x70 + (0x20 * (i))) -#define CSI2_CTX_CTRL1_GENERIC BIT(30) -#define CSI2_CTX_CTRL1_TRANSCODE (0xf << 24) -#define CSI2_CTX_CTRL1_FEC_NUMBER_MASK (0xff << 16) -#define CSI2_CTX_CTRL1_COUNT_MASK (0xff << 8) -#define CSI2_CTX_CTRL1_COUNT_SHIFT 8 -#define CSI2_CTX_CTRL1_EOF_EN BIT(7) -#define CSI2_CTX_CTRL1_EOL_EN BIT(6) -#define CSI2_CTX_CTRL1_CS_EN BIT(5) -#define CSI2_CTX_CTRL1_COUNT_UNLOCK BIT(4) -#define CSI2_CTX_CTRL1_PING_PONG BIT(3) -#define CSI2_CTX_CTRL1_CTX_EN BIT(0) - -#define CSI2_CTX_CTRL2(i) (0x74 + (0x20 * (i))) -#define CSI2_CTX_CTRL2_FRAME_MASK (0xffff << 16) -#define CSI2_CTX_CTRL2_FRAME_SHIFT 16 -#define CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT 13 -#define CSI2_CTX_CTRL2_USER_DEF_MAP_MASK \ - (0x3 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT) -#define CSI2_CTX_CTRL2_VIRTUAL_ID_MASK (3 << 11) -#define CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT 11 -#define CSI2_CTX_CTRL2_DPCM_PRED (1 << 10) -#define CSI2_CTX_CTRL2_FORMAT_MASK (0x3ff << 0) -#define CSI2_CTX_CTRL2_FORMAT_SHIFT 0 - -#define CSI2_CTX_DAT_OFST(i) (0x78 + (0x20 * (i))) -#define CSI2_CTX_DAT_OFST_MASK (0xfff << 5) - -#define CSI2_CTX_PING_ADDR(i) (0x7c + (0x20 * (i))) -#define CSI2_CTX_PING_ADDR_MASK 0xffffffe0 - -#define CSI2_CTX_PONG_ADDR(i) (0x80 + (0x20 * (i))) -#define CSI2_CTX_PONG_ADDR_MASK CSI2_CTX_PING_ADDR_MASK - -#define CSI2_CTX_IRQENABLE(i) (0x84 + (0x20 * (i))) -#define CSI2_CTX_IRQSTATUS(i) (0x88 + (0x20 * (i))) - -#define CSI2_CTX_CTRL3(i) (0x8c + (0x20 * (i))) -#define CSI2_CTX_CTRL3_ALPHA_SHIFT 5 -#define CSI2_CTX_CTRL3_ALPHA_MASK \ - (0x3fff << CSI2_CTX_CTRL3_ALPHA_SHIFT) - -/* Shared bits across CSI2_CTX_IRQENABLE and IRQSTATUS */ -#define CSI2_CTX_IRQ_ECC_CORRECTION BIT(8) -#define CSI2_CTX_IRQ_LINE_NUMBER BIT(7) -#define CSI2_CTX_IRQ_FRAME_NUMBER BIT(6) -#define CSI2_CTX_IRQ_CS BIT(5) -#define CSI2_CTX_IRQ_LE BIT(3) -#define CSI2_CTX_IRQ_LS BIT(2) -#define CSI2_CTX_IRQ_FE BIT(1) -#define CSI2_CTX_IRQ_FS BIT(0) - -/* ISS BTE */ -#define BTE_CTRL (0x0030) -#define BTE_CTRL_BW_LIMITER_MASK (0x3ff << 22) -#define BTE_CTRL_BW_LIMITER_SHIFT 22 - -/* ISS ISP_SYS1 */ -#define ISP5_REVISION (0x0000) -#define ISP5_SYSCONFIG (0x0010) -#define ISP5_SYSCONFIG_STANDBYMODE_MASK (3 << 4) -#define ISP5_SYSCONFIG_STANDBYMODE_FORCE (0 << 4) -#define ISP5_SYSCONFIG_STANDBYMODE_NO (1 << 4) -#define ISP5_SYSCONFIG_STANDBYMODE_SMART (2 << 4) -#define ISP5_SYSCONFIG_SOFTRESET (1 << 1) - -#define ISP5_IRQSTATUS(i) (0x0028 + (0x10 * (i))) -#define ISP5_IRQENABLE_SET(i) (0x002c + (0x10 * (i))) -#define ISP5_IRQENABLE_CLR(i) (0x0030 + (0x10 * (i))) - -/* Bits shared for ISP5_IRQ* registers */ -#define ISP5_IRQ_OCP_ERR BIT(31) -#define ISP5_IRQ_IPIPE_INT_DPC_RNEW1 BIT(29) -#define ISP5_IRQ_IPIPE_INT_DPC_RNEW0 BIT(28) -#define ISP5_IRQ_IPIPE_INT_DPC_INIT BIT(27) -#define ISP5_IRQ_IPIPE_INT_EOF BIT(25) -#define ISP5_IRQ_H3A_INT_EOF BIT(24) -#define ISP5_IRQ_RSZ_INT_EOF1 BIT(23) -#define ISP5_IRQ_RSZ_INT_EOF0 BIT(22) -#define ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR BIT(19) -#define ISP5_IRQ_RSZ_FIFO_OVF BIT(18) -#define ISP5_IRQ_RSZ_INT_CYC_RSZB BIT(17) -#define ISP5_IRQ_RSZ_INT_CYC_RSZA BIT(16) -#define ISP5_IRQ_RSZ_INT_DMA BIT(15) -#define ISP5_IRQ_RSZ_INT_LAST_PIX BIT(14) -#define ISP5_IRQ_RSZ_INT_REG BIT(13) -#define ISP5_IRQ_H3A_INT BIT(12) -#define ISP5_IRQ_AF_INT BIT(11) -#define ISP5_IRQ_AEW_INT BIT(10) -#define ISP5_IRQ_IPIPEIF_IRQ BIT(9) -#define ISP5_IRQ_IPIPE_INT_HST BIT(8) -#define ISP5_IRQ_IPIPE_INT_BSC BIT(7) -#define ISP5_IRQ_IPIPE_INT_DMA BIT(6) -#define ISP5_IRQ_IPIPE_INT_LAST_PIX BIT(5) -#define ISP5_IRQ_IPIPE_INT_REG BIT(4) -#define ISP5_IRQ_ISIF_INT(i) BIT(i) - -#define ISP5_CTRL (0x006c) -#define ISP5_CTRL_MSTANDBY BIT(24) -#define ISP5_CTRL_VD_PULSE_EXT BIT(23) -#define ISP5_CTRL_MSTANDBY_WAIT BIT(20) -#define ISP5_CTRL_BL_CLK_ENABLE BIT(15) -#define ISP5_CTRL_ISIF_CLK_ENABLE BIT(14) -#define ISP5_CTRL_H3A_CLK_ENABLE BIT(13) -#define ISP5_CTRL_RSZ_CLK_ENABLE BIT(12) -#define ISP5_CTRL_IPIPE_CLK_ENABLE BIT(11) -#define ISP5_CTRL_IPIPEIF_CLK_ENABLE BIT(10) -#define ISP5_CTRL_SYNC_ENABLE BIT(9) -#define ISP5_CTRL_PSYNC_CLK_SEL BIT(8) - -/* ISS ISP ISIF register offsets */ -#define ISIF_SYNCEN (0x0000) -#define ISIF_SYNCEN_DWEN BIT(1) -#define ISIF_SYNCEN_SYEN BIT(0) - -#define ISIF_MODESET (0x0004) -#define ISIF_MODESET_INPMOD_MASK (3 << 12) -#define ISIF_MODESET_INPMOD_RAW (0 << 12) -#define ISIF_MODESET_INPMOD_YCBCR16 (1 << 12) -#define ISIF_MODESET_INPMOD_YCBCR8 (2 << 12) -#define ISIF_MODESET_CCDW_MASK (7 << 8) -#define ISIF_MODESET_CCDW_2BIT (2 << 8) -#define ISIF_MODESET_CCDMD (1 << 7) -#define ISIF_MODESET_SWEN (1 << 5) -#define ISIF_MODESET_HDPOL (1 << 3) -#define ISIF_MODESET_VDPOL (1 << 2) - -#define ISIF_SPH (0x0018) -#define ISIF_SPH_MASK (0x7fff) - -#define ISIF_LNH (0x001c) -#define ISIF_LNH_MASK (0x7fff) - -#define ISIF_LNV (0x0028) -#define ISIF_LNV_MASK (0x7fff) - -#define ISIF_HSIZE (0x0034) -#define ISIF_HSIZE_ADCR BIT(12) -#define ISIF_HSIZE_HSIZE_MASK (0xfff) - -#define ISIF_CADU (0x003c) -#define ISIF_CADU_MASK (0x7ff) - -#define ISIF_CADL (0x0040) -#define ISIF_CADL_MASK (0xffff) - -#define ISIF_CCOLP (0x004c) -#define ISIF_CCOLP_CP0_F0_R (0 << 6) -#define ISIF_CCOLP_CP0_F0_GR (1 << 6) -#define ISIF_CCOLP_CP0_F0_B (3 << 6) -#define ISIF_CCOLP_CP0_F0_GB (2 << 6) -#define ISIF_CCOLP_CP1_F0_R (0 << 4) -#define ISIF_CCOLP_CP1_F0_GR (1 << 4) -#define ISIF_CCOLP_CP1_F0_B (3 << 4) -#define ISIF_CCOLP_CP1_F0_GB (2 << 4) -#define ISIF_CCOLP_CP2_F0_R (0 << 2) -#define ISIF_CCOLP_CP2_F0_GR (1 << 2) -#define ISIF_CCOLP_CP2_F0_B (3 << 2) -#define ISIF_CCOLP_CP2_F0_GB (2 << 2) -#define ISIF_CCOLP_CP3_F0_R (0 << 0) -#define ISIF_CCOLP_CP3_F0_GR (1 << 0) -#define ISIF_CCOLP_CP3_F0_B (3 << 0) -#define ISIF_CCOLP_CP3_F0_GB (2 << 0) - -#define ISIF_VDINT(i) (0x0070 + (i) * 4) -#define ISIF_VDINT_MASK (0x7fff) - -#define ISIF_CGAMMAWD (0x0080) -#define ISIF_CGAMMAWD_GWDI_MASK (0xf << 1) -#define ISIF_CGAMMAWD_GWDI(bpp) ((16 - (bpp)) << 1) - -#define ISIF_CCDCFG (0x0088) -#define ISIF_CCDCFG_Y8POS BIT(11) - -/* ISS ISP IPIPEIF register offsets */ -#define IPIPEIF_ENABLE (0x0000) - -#define IPIPEIF_CFG1 (0x0004) -#define IPIPEIF_CFG1_INPSRC1_MASK (3 << 14) -#define IPIPEIF_CFG1_INPSRC1_VPORT_RAW (0 << 14) -#define IPIPEIF_CFG1_INPSRC1_SDRAM_RAW (1 << 14) -#define IPIPEIF_CFG1_INPSRC1_ISIF_DARKFM (2 << 14) -#define IPIPEIF_CFG1_INPSRC1_SDRAM_YUV (3 << 14) -#define IPIPEIF_CFG1_INPSRC2_MASK (3 << 2) -#define IPIPEIF_CFG1_INPSRC2_ISIF (0 << 2) -#define IPIPEIF_CFG1_INPSRC2_SDRAM_RAW (1 << 2) -#define IPIPEIF_CFG1_INPSRC2_ISIF_DARKFM (2 << 2) -#define IPIPEIF_CFG1_INPSRC2_SDRAM_YUV (3 << 2) - -#define IPIPEIF_CFG2 (0x0030) -#define IPIPEIF_CFG2_YUV8P BIT(7) -#define IPIPEIF_CFG2_YUV8 BIT(6) -#define IPIPEIF_CFG2_YUV16 BIT(3) -#define IPIPEIF_CFG2_VDPOL BIT(2) -#define IPIPEIF_CFG2_HDPOL BIT(1) -#define IPIPEIF_CFG2_INTSW BIT(0) - -#define IPIPEIF_CLKDIV (0x0040) - -/* ISS ISP IPIPE register offsets */ -#define IPIPE_SRC_EN (0x0000) -#define IPIPE_SRC_EN_EN BIT(0) - -#define IPIPE_SRC_MODE (0x0004) -#define IPIPE_SRC_MODE_WRT BIT(1) -#define IPIPE_SRC_MODE_OST BIT(0) - -#define IPIPE_SRC_FMT (0x0008) -#define IPIPE_SRC_FMT_RAW2YUV (0 << 0) -#define IPIPE_SRC_FMT_RAW2RAW (1 << 0) -#define IPIPE_SRC_FMT_RAW2STATS (2 << 0) -#define IPIPE_SRC_FMT_YUV2YUV (3 << 0) - -#define IPIPE_SRC_COL (0x000c) -#define IPIPE_SRC_COL_OO_R (0 << 6) -#define IPIPE_SRC_COL_OO_GR (1 << 6) -#define IPIPE_SRC_COL_OO_B (3 << 6) -#define IPIPE_SRC_COL_OO_GB (2 << 6) -#define IPIPE_SRC_COL_OE_R (0 << 4) -#define IPIPE_SRC_COL_OE_GR (1 << 4) -#define IPIPE_SRC_COL_OE_B (3 << 4) -#define IPIPE_SRC_COL_OE_GB (2 << 4) -#define IPIPE_SRC_COL_EO_R (0 << 2) -#define IPIPE_SRC_COL_EO_GR (1 << 2) -#define IPIPE_SRC_COL_EO_B (3 << 2) -#define IPIPE_SRC_COL_EO_GB (2 << 2) -#define IPIPE_SRC_COL_EE_R (0 << 0) -#define IPIPE_SRC_COL_EE_GR (1 << 0) -#define IPIPE_SRC_COL_EE_B (3 << 0) -#define IPIPE_SRC_COL_EE_GB (2 << 0) - -#define IPIPE_SRC_VPS (0x0010) -#define IPIPE_SRC_VPS_MASK (0xffff) - -#define IPIPE_SRC_VSZ (0x0014) -#define IPIPE_SRC_VSZ_MASK (0x1fff) - -#define IPIPE_SRC_HPS (0x0018) -#define IPIPE_SRC_HPS_MASK (0xffff) - -#define IPIPE_SRC_HSZ (0x001c) -#define IPIPE_SRC_HSZ_MASK (0x1ffe) - -#define IPIPE_SEL_SBU (0x0020) - -#define IPIPE_SRC_STA (0x0024) - -#define IPIPE_GCK_MMR (0x0028) -#define IPIPE_GCK_MMR_REG BIT(0) - -#define IPIPE_GCK_PIX (0x002c) -#define IPIPE_GCK_PIX_G3 BIT(3) -#define IPIPE_GCK_PIX_G2 BIT(2) -#define IPIPE_GCK_PIX_G1 BIT(1) -#define IPIPE_GCK_PIX_G0 BIT(0) - -#define IPIPE_DPC_LUT_EN (0x0034) -#define IPIPE_DPC_LUT_SEL (0x0038) -#define IPIPE_DPC_LUT_ADR (0x003c) -#define IPIPE_DPC_LUT_SIZ (0x0040) - -#define IPIPE_DPC_OTF_EN (0x0044) -#define IPIPE_DPC_OTF_TYP (0x0048) -#define IPIPE_DPC_OTF_2_D_THR_R (0x004c) -#define IPIPE_DPC_OTF_2_D_THR_GR (0x0050) -#define IPIPE_DPC_OTF_2_D_THR_GB (0x0054) -#define IPIPE_DPC_OTF_2_D_THR_B (0x0058) -#define IPIPE_DPC_OTF_2_C_THR_R (0x005c) -#define IPIPE_DPC_OTF_2_C_THR_GR (0x0060) -#define IPIPE_DPC_OTF_2_C_THR_GB (0x0064) -#define IPIPE_DPC_OTF_2_C_THR_B (0x0068) -#define IPIPE_DPC_OTF_3_SHF (0x006c) -#define IPIPE_DPC_OTF_3_D_THR (0x0070) -#define IPIPE_DPC_OTF_3_D_SPL (0x0074) -#define IPIPE_DPC_OTF_3_D_MIN (0x0078) -#define IPIPE_DPC_OTF_3_D_MAX (0x007c) -#define IPIPE_DPC_OTF_3_C_THR (0x0080) -#define IPIPE_DPC_OTF_3_C_SLP (0x0084) -#define IPIPE_DPC_OTF_3_C_MIN (0x0088) -#define IPIPE_DPC_OTF_3_C_MAX (0x008c) - -#define IPIPE_LSC_VOFT (0x0090) -#define IPIPE_LSC_VA2 (0x0094) -#define IPIPE_LSC_VA1 (0x0098) -#define IPIPE_LSC_VS (0x009c) -#define IPIPE_LSC_HOFT (0x00a0) -#define IPIPE_LSC_HA2 (0x00a4) -#define IPIPE_LSC_HA1 (0x00a8) -#define IPIPE_LSC_HS (0x00ac) -#define IPIPE_LSC_GAN_R (0x00b0) -#define IPIPE_LSC_GAN_GR (0x00b4) -#define IPIPE_LSC_GAN_GB (0x00b8) -#define IPIPE_LSC_GAN_B (0x00bc) -#define IPIPE_LSC_OFT_R (0x00c0) -#define IPIPE_LSC_OFT_GR (0x00c4) -#define IPIPE_LSC_OFT_GB (0x00c8) -#define IPIPE_LSC_OFT_B (0x00cc) -#define IPIPE_LSC_SHF (0x00d0) -#define IPIPE_LSC_MAX (0x00d4) - -#define IPIPE_D2F_1ST_EN (0x00d8) -#define IPIPE_D2F_1ST_TYP (0x00dc) -#define IPIPE_D2F_1ST_THR_00 (0x00e0) -#define IPIPE_D2F_1ST_THR_01 (0x00e4) -#define IPIPE_D2F_1ST_THR_02 (0x00e8) -#define IPIPE_D2F_1ST_THR_03 (0x00ec) -#define IPIPE_D2F_1ST_THR_04 (0x00f0) -#define IPIPE_D2F_1ST_THR_05 (0x00f4) -#define IPIPE_D2F_1ST_THR_06 (0x00f8) -#define IPIPE_D2F_1ST_THR_07 (0x00fc) -#define IPIPE_D2F_1ST_STR_00 (0x0100) -#define IPIPE_D2F_1ST_STR_01 (0x0104) -#define IPIPE_D2F_1ST_STR_02 (0x0108) -#define IPIPE_D2F_1ST_STR_03 (0x010c) -#define IPIPE_D2F_1ST_STR_04 (0x0110) -#define IPIPE_D2F_1ST_STR_05 (0x0114) -#define IPIPE_D2F_1ST_STR_06 (0x0118) -#define IPIPE_D2F_1ST_STR_07 (0x011c) -#define IPIPE_D2F_1ST_SPR_00 (0x0120) -#define IPIPE_D2F_1ST_SPR_01 (0x0124) -#define IPIPE_D2F_1ST_SPR_02 (0x0128) -#define IPIPE_D2F_1ST_SPR_03 (0x012c) -#define IPIPE_D2F_1ST_SPR_04 (0x0130) -#define IPIPE_D2F_1ST_SPR_05 (0x0134) -#define IPIPE_D2F_1ST_SPR_06 (0x0138) -#define IPIPE_D2F_1ST_SPR_07 (0x013c) -#define IPIPE_D2F_1ST_EDG_MIN (0x0140) -#define IPIPE_D2F_1ST_EDG_MAX (0x0144) -#define IPIPE_D2F_2ND_EN (0x0148) -#define IPIPE_D2F_2ND_TYP (0x014c) -#define IPIPE_D2F_2ND_THR00 (0x0150) -#define IPIPE_D2F_2ND_THR01 (0x0154) -#define IPIPE_D2F_2ND_THR02 (0x0158) -#define IPIPE_D2F_2ND_THR03 (0x015c) -#define IPIPE_D2F_2ND_THR04 (0x0160) -#define IPIPE_D2F_2ND_THR05 (0x0164) -#define IPIPE_D2F_2ND_THR06 (0x0168) -#define IPIPE_D2F_2ND_THR07 (0x016c) -#define IPIPE_D2F_2ND_STR_00 (0x0170) -#define IPIPE_D2F_2ND_STR_01 (0x0174) -#define IPIPE_D2F_2ND_STR_02 (0x0178) -#define IPIPE_D2F_2ND_STR_03 (0x017c) -#define IPIPE_D2F_2ND_STR_04 (0x0180) -#define IPIPE_D2F_2ND_STR_05 (0x0184) -#define IPIPE_D2F_2ND_STR_06 (0x0188) -#define IPIPE_D2F_2ND_STR_07 (0x018c) -#define IPIPE_D2F_2ND_SPR_00 (0x0190) -#define IPIPE_D2F_2ND_SPR_01 (0x0194) -#define IPIPE_D2F_2ND_SPR_02 (0x0198) -#define IPIPE_D2F_2ND_SPR_03 (0x019c) -#define IPIPE_D2F_2ND_SPR_04 (0x01a0) -#define IPIPE_D2F_2ND_SPR_05 (0x01a4) -#define IPIPE_D2F_2ND_SPR_06 (0x01a8) -#define IPIPE_D2F_2ND_SPR_07 (0x01ac) -#define IPIPE_D2F_2ND_EDG_MIN (0x01b0) -#define IPIPE_D2F_2ND_EDG_MAX (0x01b4) - -#define IPIPE_GIC_EN (0x01b8) -#define IPIPE_GIC_TYP (0x01bc) -#define IPIPE_GIC_GAN (0x01c0) -#define IPIPE_GIC_NFGAIN (0x01c4) -#define IPIPE_GIC_THR (0x01c8) -#define IPIPE_GIC_SLP (0x01cc) - -#define IPIPE_WB2_OFT_R (0x01d0) -#define IPIPE_WB2_OFT_GR (0x01d4) -#define IPIPE_WB2_OFT_GB (0x01d8) -#define IPIPE_WB2_OFT_B (0x01dc) - -#define IPIPE_WB2_WGN_R (0x01e0) -#define IPIPE_WB2_WGN_GR (0x01e4) -#define IPIPE_WB2_WGN_GB (0x01e8) -#define IPIPE_WB2_WGN_B (0x01ec) - -#define IPIPE_CFA_MODE (0x01f0) -#define IPIPE_CFA_2DIR_HPF_THR (0x01f4) -#define IPIPE_CFA_2DIR_HPF_SLP (0x01f8) -#define IPIPE_CFA_2DIR_MIX_THR (0x01fc) -#define IPIPE_CFA_2DIR_MIX_SLP (0x0200) -#define IPIPE_CFA_2DIR_DIR_TRH (0x0204) -#define IPIPE_CFA_2DIR_DIR_SLP (0x0208) -#define IPIPE_CFA_2DIR_NDWT (0x020c) -#define IPIPE_CFA_MONO_HUE_FRA (0x0210) -#define IPIPE_CFA_MONO_EDG_THR (0x0214) -#define IPIPE_CFA_MONO_THR_MIN (0x0218) - -#define IPIPE_CFA_MONO_THR_SLP (0x021c) -#define IPIPE_CFA_MONO_SLP_MIN (0x0220) -#define IPIPE_CFA_MONO_SLP_SLP (0x0224) -#define IPIPE_CFA_MONO_LPWT (0x0228) - -#define IPIPE_RGB1_MUL_RR (0x022c) -#define IPIPE_RGB1_MUL_GR (0x0230) -#define IPIPE_RGB1_MUL_BR (0x0234) -#define IPIPE_RGB1_MUL_RG (0x0238) -#define IPIPE_RGB1_MUL_GG (0x023c) -#define IPIPE_RGB1_MUL_BG (0x0240) -#define IPIPE_RGB1_MUL_RB (0x0244) -#define IPIPE_RGB1_MUL_GB (0x0248) -#define IPIPE_RGB1_MUL_BB (0x024c) -#define IPIPE_RGB1_OFT_OR (0x0250) -#define IPIPE_RGB1_OFT_OG (0x0254) -#define IPIPE_RGB1_OFT_OB (0x0258) -#define IPIPE_GMM_CFG (0x025c) -#define IPIPE_RGB2_MUL_RR (0x0260) -#define IPIPE_RGB2_MUL_GR (0x0264) -#define IPIPE_RGB2_MUL_BR (0x0268) -#define IPIPE_RGB2_MUL_RG (0x026c) -#define IPIPE_RGB2_MUL_GG (0x0270) -#define IPIPE_RGB2_MUL_BG (0x0274) -#define IPIPE_RGB2_MUL_RB (0x0278) -#define IPIPE_RGB2_MUL_GB (0x027c) -#define IPIPE_RGB2_MUL_BB (0x0280) -#define IPIPE_RGB2_OFT_OR (0x0284) -#define IPIPE_RGB2_OFT_OG (0x0288) -#define IPIPE_RGB2_OFT_OB (0x028c) - -#define IPIPE_YUV_ADJ (0x0294) -#define IPIPE_YUV_MUL_RY (0x0298) -#define IPIPE_YUV_MUL_GY (0x029c) -#define IPIPE_YUV_MUL_BY (0x02a0) -#define IPIPE_YUV_MUL_RCB (0x02a4) -#define IPIPE_YUV_MUL_GCB (0x02a8) -#define IPIPE_YUV_MUL_BCB (0x02ac) -#define IPIPE_YUV_MUL_RCR (0x02b0) -#define IPIPE_YUV_MUL_GCR (0x02b4) -#define IPIPE_YUV_MUL_BCR (0x02b8) -#define IPIPE_YUV_OFT_Y (0x02bc) -#define IPIPE_YUV_OFT_CB (0x02c0) -#define IPIPE_YUV_OFT_CR (0x02c4) - -#define IPIPE_YUV_PHS (0x02c8) -#define IPIPE_YUV_PHS_LPF BIT(1) -#define IPIPE_YUV_PHS_POS BIT(0) - -#define IPIPE_YEE_EN (0x02d4) -#define IPIPE_YEE_TYP (0x02d8) -#define IPIPE_YEE_SHF (0x02dc) -#define IPIPE_YEE_MUL_00 (0x02e0) -#define IPIPE_YEE_MUL_01 (0x02e4) -#define IPIPE_YEE_MUL_02 (0x02e8) -#define IPIPE_YEE_MUL_10 (0x02ec) -#define IPIPE_YEE_MUL_11 (0x02f0) -#define IPIPE_YEE_MUL_12 (0x02f4) -#define IPIPE_YEE_MUL_20 (0x02f8) -#define IPIPE_YEE_MUL_21 (0x02fc) -#define IPIPE_YEE_MUL_22 (0x0300) -#define IPIPE_YEE_THR (0x0304) -#define IPIPE_YEE_E_GAN (0x0308) -#define IPIPE_YEE_E_THR_1 (0x030c) -#define IPIPE_YEE_E_THR_2 (0x0310) -#define IPIPE_YEE_G_GAN (0x0314) -#define IPIPE_YEE_G_OFT (0x0318) - -#define IPIPE_CAR_EN (0x031c) -#define IPIPE_CAR_TYP (0x0320) -#define IPIPE_CAR_SW (0x0324) -#define IPIPE_CAR_HPF_TYP (0x0328) -#define IPIPE_CAR_HPF_SHF (0x032c) -#define IPIPE_CAR_HPF_THR (0x0330) -#define IPIPE_CAR_GN1_GAN (0x0334) -#define IPIPE_CAR_GN1_SHF (0x0338) -#define IPIPE_CAR_GN1_MIN (0x033c) -#define IPIPE_CAR_GN2_GAN (0x0340) -#define IPIPE_CAR_GN2_SHF (0x0344) -#define IPIPE_CAR_GN2_MIN (0x0348) -#define IPIPE_CGS_EN (0x034c) -#define IPIPE_CGS_GN1_L_THR (0x0350) -#define IPIPE_CGS_GN1_L_GAIN (0x0354) -#define IPIPE_CGS_GN1_L_SHF (0x0358) -#define IPIPE_CGS_GN1_L_MIN (0x035c) -#define IPIPE_CGS_GN1_H_THR (0x0360) -#define IPIPE_CGS_GN1_H_GAIN (0x0364) -#define IPIPE_CGS_GN1_H_SHF (0x0368) -#define IPIPE_CGS_GN1_H_MIN (0x036c) -#define IPIPE_CGS_GN2_L_THR (0x0370) -#define IPIPE_CGS_GN2_L_GAIN (0x0374) -#define IPIPE_CGS_GN2_L_SHF (0x0378) -#define IPIPE_CGS_GN2_L_MIN (0x037c) - -#define IPIPE_BOX_EN (0x0380) -#define IPIPE_BOX_MODE (0x0384) -#define IPIPE_BOX_TYP (0x0388) -#define IPIPE_BOX_SHF (0x038c) -#define IPIPE_BOX_SDR_SAD_H (0x0390) -#define IPIPE_BOX_SDR_SAD_L (0x0394) - -#define IPIPE_HST_EN (0x039c) -#define IPIPE_HST_MODE (0x03a0) -#define IPIPE_HST_SEL (0x03a4) -#define IPIPE_HST_PARA (0x03a8) -#define IPIPE_HST_0_VPS (0x03ac) -#define IPIPE_HST_0_VSZ (0x03b0) -#define IPIPE_HST_0_HPS (0x03b4) -#define IPIPE_HST_0_HSZ (0x03b8) -#define IPIPE_HST_1_VPS (0x03bc) -#define IPIPE_HST_1_VSZ (0x03c0) -#define IPIPE_HST_1_HPS (0x03c4) -#define IPIPE_HST_1_HSZ (0x03c8) -#define IPIPE_HST_2_VPS (0x03cc) -#define IPIPE_HST_2_VSZ (0x03d0) -#define IPIPE_HST_2_HPS (0x03d4) -#define IPIPE_HST_2_HSZ (0x03d8) -#define IPIPE_HST_3_VPS (0x03dc) -#define IPIPE_HST_3_VSZ (0x03e0) -#define IPIPE_HST_3_HPS (0x03e4) -#define IPIPE_HST_3_HSZ (0x03e8) -#define IPIPE_HST_TBL (0x03ec) -#define IPIPE_HST_MUL_R (0x03f0) -#define IPIPE_HST_MUL_GR (0x03f4) -#define IPIPE_HST_MUL_GB (0x03f8) -#define IPIPE_HST_MUL_B (0x03fc) - -#define IPIPE_BSC_EN (0x0400) -#define IPIPE_BSC_MODE (0x0404) -#define IPIPE_BSC_TYP (0x0408) -#define IPIPE_BSC_ROW_VCT (0x040c) -#define IPIPE_BSC_ROW_SHF (0x0410) -#define IPIPE_BSC_ROW_VPO (0x0414) -#define IPIPE_BSC_ROW_VNU (0x0418) -#define IPIPE_BSC_ROW_VSKIP (0x041c) -#define IPIPE_BSC_ROW_HPO (0x0420) -#define IPIPE_BSC_ROW_HNU (0x0424) -#define IPIPE_BSC_ROW_HSKIP (0x0428) -#define IPIPE_BSC_COL_VCT (0x042c) -#define IPIPE_BSC_COL_SHF (0x0430) -#define IPIPE_BSC_COL_VPO (0x0434) -#define IPIPE_BSC_COL_VNU (0x0438) -#define IPIPE_BSC_COL_VSKIP (0x043c) -#define IPIPE_BSC_COL_HPO (0x0440) -#define IPIPE_BSC_COL_HNU (0x0444) -#define IPIPE_BSC_COL_HSKIP (0x0448) - -#define IPIPE_BSC_EN (0x0400) - -/* ISS ISP Resizer register offsets */ -#define RSZ_REVISION (0x0000) -#define RSZ_SYSCONFIG (0x0004) -#define RSZ_SYSCONFIG_RSZB_CLK_EN BIT(9) -#define RSZ_SYSCONFIG_RSZA_CLK_EN BIT(8) - -#define RSZ_IN_FIFO_CTRL (0x000c) -#define RSZ_IN_FIFO_CTRL_THRLD_LOW_MASK (0x1ff << 16) -#define RSZ_IN_FIFO_CTRL_THRLD_LOW_SHIFT 16 -#define RSZ_IN_FIFO_CTRL_THRLD_HIGH_MASK (0x1ff << 0) -#define RSZ_IN_FIFO_CTRL_THRLD_HIGH_SHIFT 0 - -#define RSZ_FRACDIV (0x0008) -#define RSZ_FRACDIV_MASK (0xffff) - -#define RSZ_SRC_EN (0x0020) -#define RSZ_SRC_EN_SRC_EN BIT(0) - -#define RSZ_SRC_MODE (0x0024) -#define RSZ_SRC_MODE_OST BIT(0) -#define RSZ_SRC_MODE_WRT BIT(1) - -#define RSZ_SRC_FMT0 (0x0028) -#define RSZ_SRC_FMT0_BYPASS BIT(1) -#define RSZ_SRC_FMT0_SEL BIT(0) - -#define RSZ_SRC_FMT1 (0x002c) -#define RSZ_SRC_FMT1_IN420 BIT(1) - -#define RSZ_SRC_VPS (0x0030) -#define RSZ_SRC_VSZ (0x0034) -#define RSZ_SRC_HPS (0x0038) -#define RSZ_SRC_HSZ (0x003c) -#define RSZ_DMA_RZA (0x0040) -#define RSZ_DMA_RZB (0x0044) -#define RSZ_DMA_STA (0x0048) -#define RSZ_GCK_MMR (0x004c) -#define RSZ_GCK_MMR_MMR BIT(0) - -#define RSZ_GCK_SDR (0x0054) -#define RSZ_GCK_SDR_CORE BIT(0) - -#define RSZ_IRQ_RZA (0x0058) -#define RSZ_IRQ_RZA_MASK (0x1fff) - -#define RSZ_IRQ_RZB (0x005c) -#define RSZ_IRQ_RZB_MASK (0x1fff) - -#define RSZ_YUV_Y_MIN (0x0060) -#define RSZ_YUV_Y_MAX (0x0064) -#define RSZ_YUV_C_MIN (0x0068) -#define RSZ_YUV_C_MAX (0x006c) - -#define RSZ_SEQ (0x0074) -#define RSZ_SEQ_HRVB BIT(2) -#define RSZ_SEQ_HRVA BIT(0) - -#define RZA_EN (0x0078) -#define RZA_MODE (0x007c) -#define RZA_MODE_ONE_SHOT BIT(0) - -#define RZA_420 (0x0080) -#define RZA_I_VPS (0x0084) -#define RZA_I_HPS (0x0088) -#define RZA_O_VSZ (0x008c) -#define RZA_O_HSZ (0x0090) -#define RZA_V_PHS_Y (0x0094) -#define RZA_V_PHS_C (0x0098) -#define RZA_V_DIF (0x009c) -#define RZA_V_TYP (0x00a0) -#define RZA_V_LPF (0x00a4) -#define RZA_H_PHS (0x00a8) -#define RZA_H_DIF (0x00b0) -#define RZA_H_TYP (0x00b4) -#define RZA_H_LPF (0x00b8) -#define RZA_DWN_EN (0x00bc) -#define RZA_SDR_Y_BAD_H (0x00d0) -#define RZA_SDR_Y_BAD_L (0x00d4) -#define RZA_SDR_Y_SAD_H (0x00d8) -#define RZA_SDR_Y_SAD_L (0x00dc) -#define RZA_SDR_Y_OFT (0x00e0) -#define RZA_SDR_Y_PTR_S (0x00e4) -#define RZA_SDR_Y_PTR_E (0x00e8) -#define RZA_SDR_C_BAD_H (0x00ec) -#define RZA_SDR_C_BAD_L (0x00f0) -#define RZA_SDR_C_SAD_H (0x00f4) -#define RZA_SDR_C_SAD_L (0x00f8) -#define RZA_SDR_C_OFT (0x00fc) -#define RZA_SDR_C_PTR_S (0x0100) -#define RZA_SDR_C_PTR_E (0x0104) - -#define RZB_EN (0x0108) -#define RZB_MODE (0x010c) -#define RZB_420 (0x0110) -#define RZB_I_VPS (0x0114) -#define RZB_I_HPS (0x0118) -#define RZB_O_VSZ (0x011c) -#define RZB_O_HSZ (0x0120) - -#define RZB_V_DIF (0x012c) -#define RZB_V_TYP (0x0130) -#define RZB_V_LPF (0x0134) - -#define RZB_H_DIF (0x0140) -#define RZB_H_TYP (0x0144) -#define RZB_H_LPF (0x0148) - -#define RZB_SDR_Y_BAD_H (0x0160) -#define RZB_SDR_Y_BAD_L (0x0164) -#define RZB_SDR_Y_SAD_H (0x0168) -#define RZB_SDR_Y_SAD_L (0x016c) -#define RZB_SDR_Y_OFT (0x0170) -#define RZB_SDR_Y_PTR_S (0x0174) -#define RZB_SDR_Y_PTR_E (0x0178) -#define RZB_SDR_C_BAD_H (0x017c) -#define RZB_SDR_C_BAD_L (0x0180) -#define RZB_SDR_C_SAD_H (0x0184) -#define RZB_SDR_C_SAD_L (0x0188) - -#define RZB_SDR_C_PTR_S (0x0190) -#define RZB_SDR_C_PTR_E (0x0194) - -/* Shared Bitmasks between RZA & RZB */ -#define RSZ_EN_EN BIT(0) - -#define RSZ_420_CEN BIT(1) -#define RSZ_420_YEN BIT(0) - -#define RSZ_I_VPS_MASK (0x1fff) - -#define RSZ_I_HPS_MASK (0x1fff) - -#define RSZ_O_VSZ_MASK (0x1fff) - -#define RSZ_O_HSZ_MASK (0x1ffe) - -#define RSZ_V_PHS_Y_MASK (0x3fff) - -#define RSZ_V_PHS_C_MASK (0x3fff) - -#define RSZ_V_DIF_MASK (0x3fff) - -#define RSZ_V_TYP_C BIT(1) -#define RSZ_V_TYP_Y BIT(0) - -#define RSZ_V_LPF_C_MASK (0x3f << 6) -#define RSZ_V_LPF_C_SHIFT 6 -#define RSZ_V_LPF_Y_MASK (0x3f << 0) -#define RSZ_V_LPF_Y_SHIFT 0 - -#define RSZ_H_PHS_MASK (0x3fff) - -#define RSZ_H_DIF_MASK (0x3fff) - -#define RSZ_H_TYP_C BIT(1) -#define RSZ_H_TYP_Y BIT(0) - -#define RSZ_H_LPF_C_MASK (0x3f << 6) -#define RSZ_H_LPF_C_SHIFT 6 -#define RSZ_H_LPF_Y_MASK (0x3f << 0) -#define RSZ_H_LPF_Y_SHIFT 0 - -#define RSZ_DWN_EN_DWN_EN BIT(0) - -#endif /* _OMAP4_ISS_REGS_H_ */ diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c deleted file mode 100644 index 58e698ef9108..000000000000 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ /dev/null @@ -1,884 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * TI OMAP4 ISS V4L2 Driver - ISP RESIZER module - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "iss.h" -#include "iss_regs.h" -#include "iss_resizer.h" - -static const unsigned int resizer_fmts[] = { - MEDIA_BUS_FMT_UYVY8_1X16, - MEDIA_BUS_FMT_YUYV8_1X16, -}; - -/* - * resizer_print_status - Print current RESIZER Module register values. - * @resizer: Pointer to ISS ISP RESIZER device. - * - * Also prints other debug information stored in the RESIZER module. - */ -#define RSZ_PRINT_REGISTER(iss, name)\ - dev_dbg(iss->dev, "###RSZ " #name "=0x%08x\n", \ - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_##name)) - -#define RZA_PRINT_REGISTER(iss, name)\ - dev_dbg(iss->dev, "###RZA " #name "=0x%08x\n", \ - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_##name)) - -static void resizer_print_status(struct iss_resizer_device *resizer) -{ - struct iss_device *iss = to_iss_device(resizer); - - dev_dbg(iss->dev, "-------------RESIZER Register dump-------------\n"); - - RSZ_PRINT_REGISTER(iss, SYSCONFIG); - RSZ_PRINT_REGISTER(iss, IN_FIFO_CTRL); - RSZ_PRINT_REGISTER(iss, FRACDIV); - RSZ_PRINT_REGISTER(iss, SRC_EN); - RSZ_PRINT_REGISTER(iss, SRC_MODE); - RSZ_PRINT_REGISTER(iss, SRC_FMT0); - RSZ_PRINT_REGISTER(iss, SRC_FMT1); - RSZ_PRINT_REGISTER(iss, SRC_VPS); - RSZ_PRINT_REGISTER(iss, SRC_VSZ); - RSZ_PRINT_REGISTER(iss, SRC_HPS); - RSZ_PRINT_REGISTER(iss, SRC_HSZ); - RSZ_PRINT_REGISTER(iss, DMA_RZA); - RSZ_PRINT_REGISTER(iss, DMA_RZB); - RSZ_PRINT_REGISTER(iss, DMA_STA); - RSZ_PRINT_REGISTER(iss, GCK_MMR); - RSZ_PRINT_REGISTER(iss, GCK_SDR); - RSZ_PRINT_REGISTER(iss, IRQ_RZA); - RSZ_PRINT_REGISTER(iss, IRQ_RZB); - RSZ_PRINT_REGISTER(iss, YUV_Y_MIN); - RSZ_PRINT_REGISTER(iss, YUV_Y_MAX); - RSZ_PRINT_REGISTER(iss, YUV_C_MIN); - RSZ_PRINT_REGISTER(iss, YUV_C_MAX); - RSZ_PRINT_REGISTER(iss, SEQ); - - RZA_PRINT_REGISTER(iss, EN); - RZA_PRINT_REGISTER(iss, MODE); - RZA_PRINT_REGISTER(iss, 420); - RZA_PRINT_REGISTER(iss, I_VPS); - RZA_PRINT_REGISTER(iss, I_HPS); - RZA_PRINT_REGISTER(iss, O_VSZ); - RZA_PRINT_REGISTER(iss, O_HSZ); - RZA_PRINT_REGISTER(iss, V_PHS_Y); - RZA_PRINT_REGISTER(iss, V_PHS_C); - RZA_PRINT_REGISTER(iss, V_DIF); - RZA_PRINT_REGISTER(iss, V_TYP); - RZA_PRINT_REGISTER(iss, V_LPF); - RZA_PRINT_REGISTER(iss, H_PHS); - RZA_PRINT_REGISTER(iss, H_DIF); - RZA_PRINT_REGISTER(iss, H_TYP); - RZA_PRINT_REGISTER(iss, H_LPF); - RZA_PRINT_REGISTER(iss, DWN_EN); - RZA_PRINT_REGISTER(iss, SDR_Y_BAD_H); - RZA_PRINT_REGISTER(iss, SDR_Y_BAD_L); - RZA_PRINT_REGISTER(iss, SDR_Y_SAD_H); - RZA_PRINT_REGISTER(iss, SDR_Y_SAD_L); - RZA_PRINT_REGISTER(iss, SDR_Y_OFT); - RZA_PRINT_REGISTER(iss, SDR_Y_PTR_S); - RZA_PRINT_REGISTER(iss, SDR_Y_PTR_E); - RZA_PRINT_REGISTER(iss, SDR_C_BAD_H); - RZA_PRINT_REGISTER(iss, SDR_C_BAD_L); - RZA_PRINT_REGISTER(iss, SDR_C_SAD_H); - RZA_PRINT_REGISTER(iss, SDR_C_SAD_L); - RZA_PRINT_REGISTER(iss, SDR_C_OFT); - RZA_PRINT_REGISTER(iss, SDR_C_PTR_S); - RZA_PRINT_REGISTER(iss, SDR_C_PTR_E); - - dev_dbg(iss->dev, "-----------------------------------------------\n"); -} - -/* - * resizer_enable - Enable/Disable RESIZER. - * @enable: enable flag - * - */ -static void resizer_enable(struct iss_resizer_device *resizer, u8 enable) -{ - struct iss_device *iss = to_iss_device(resizer); - - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_EN, - RSZ_SRC_EN_SRC_EN, enable ? RSZ_SRC_EN_SRC_EN : 0); - - /* TODO: Enable RSZB */ - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_EN, RSZ_EN_EN, - enable ? RSZ_EN_EN : 0); -} - -/* ----------------------------------------------------------------------------- - * Format- and pipeline-related configuration helpers - */ - -/* - * resizer_set_outaddr - Set memory address to save output image - * @resizer: Pointer to ISP RESIZER device. - * @addr: 32-bit memory address aligned on 32 byte boundary. - * - * Sets the memory address where the output will be saved. - */ -static void resizer_set_outaddr(struct iss_resizer_device *resizer, u32 addr) -{ - struct iss_device *iss = to_iss_device(resizer); - struct v4l2_mbus_framefmt *informat, *outformat; - - informat = &resizer->formats[RESIZER_PAD_SINK]; - outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM]; - - /* Save address split in Base Address H & L */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_BAD_H, - (addr >> 16) & 0xffff); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_BAD_L, - addr & 0xffff); - - /* SAD = BAD */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_SAD_H, - (addr >> 16) & 0xffff); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_SAD_L, - addr & 0xffff); - - /* Program UV buffer address... Hardcoded to be contiguous! */ - if ((informat->code == MEDIA_BUS_FMT_UYVY8_1X16) && - (outformat->code == MEDIA_BUS_FMT_YUYV8_1_5X8)) { - u32 c_addr = addr + resizer->video_out.bpl_value - * outformat->height; - - /* Ensure Y_BAD_L[6:0] = C_BAD_L[6:0]*/ - if ((c_addr ^ addr) & 0x7f) { - c_addr &= ~0x7f; - c_addr += 0x80; - c_addr |= addr & 0x7f; - } - - /* Save address split in Base Address H & L */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_BAD_H, - (c_addr >> 16) & 0xffff); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_BAD_L, - c_addr & 0xffff); - - /* SAD = BAD */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_SAD_H, - (c_addr >> 16) & 0xffff); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_SAD_L, - c_addr & 0xffff); - } -} - -static void resizer_configure(struct iss_resizer_device *resizer) -{ - struct iss_device *iss = to_iss_device(resizer); - struct v4l2_mbus_framefmt *informat, *outformat; - - informat = &resizer->formats[RESIZER_PAD_SINK]; - outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM]; - - /* Disable pass-through more. Despite its name, the BYPASS bit controls - * pass-through mode, not bypass mode. - */ - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_FMT0, - RSZ_SRC_FMT0_BYPASS); - - /* Select RSZ input */ - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_FMT0, - RSZ_SRC_FMT0_SEL, - resizer->input == RESIZER_INPUT_IPIPEIF ? - RSZ_SRC_FMT0_SEL : 0); - - /* RSZ ignores WEN signal from IPIPE/IPIPEIF */ - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_MODE, - RSZ_SRC_MODE_WRT); - - /* Set Resizer in free-running mode */ - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_MODE, - RSZ_SRC_MODE_OST); - - /* Init Resizer A */ - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_MODE, - RZA_MODE_ONE_SHOT); - - /* Set size related things now */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_VPS, 0); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_HPS, 0); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_VSZ, - informat->height - 2); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_HSZ, - informat->width - 1); - - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_I_VPS, 0); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_I_HPS, 0); - - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_O_VSZ, - outformat->height - 2); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_O_HSZ, - outformat->width - 1); - - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_V_DIF, 0x100); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_H_DIF, 0x100); - - /* Buffer output settings */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_PTR_S, 0); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_PTR_E, - outformat->height - 1); - - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_OFT, - resizer->video_out.bpl_value); - - /* UYVY -> NV12 conversion */ - if ((informat->code == MEDIA_BUS_FMT_UYVY8_1X16) && - (outformat->code == MEDIA_BUS_FMT_YUYV8_1_5X8)) { - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_420, - RSZ_420_CEN | RSZ_420_YEN); - - /* UV Buffer output settings */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_PTR_S, - 0); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_PTR_E, - outformat->height - 1); - - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_OFT, - resizer->video_out.bpl_value); - } else { - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_420, 0); - } -} - -/* ----------------------------------------------------------------------------- - * Interrupt handling - */ - -static void resizer_isr_buffer(struct iss_resizer_device *resizer) -{ - struct iss_buffer *buffer; - - /* The whole resizer needs to be stopped. Disabling RZA only produces - * input FIFO overflows, most probably when the next frame is received. - */ - resizer_enable(resizer, 0); - - buffer = omap4iss_video_buffer_next(&resizer->video_out); - if (!buffer) - return; - - resizer_set_outaddr(resizer, buffer->iss_addr); - - resizer_enable(resizer, 1); -} - -/* - * omap4iss_resizer_isr - Configure resizer during interframe time. - * @resizer: Pointer to ISP RESIZER device. - * @events: RESIZER events - */ -void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events) -{ - struct iss_device *iss = to_iss_device(resizer); - struct iss_pipeline *pipe = - to_iss_pipeline(&resizer->subdev.entity); - - if (events & (ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | - ISP5_IRQ_RSZ_FIFO_OVF)) { - dev_dbg(iss->dev, "RSZ Err: FIFO_IN_BLK:%d, FIFO_OVF:%d\n", - events & ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR ? 1 : 0, - events & ISP5_IRQ_RSZ_FIFO_OVF ? 1 : 0); - omap4iss_pipeline_cancel_stream(pipe); - } - - if (omap4iss_module_sync_is_stopping(&resizer->wait, - &resizer->stopping)) - return; - - if (events & ISP5_IRQ_RSZ_INT_DMA) - resizer_isr_buffer(resizer); -} - -/* ----------------------------------------------------------------------------- - * ISS video operations - */ - -static int resizer_video_queue(struct iss_video *video, - struct iss_buffer *buffer) -{ - struct iss_resizer_device *resizer = container_of(video, - struct iss_resizer_device, video_out); - - if (!(resizer->output & RESIZER_OUTPUT_MEMORY)) - return -ENODEV; - - resizer_set_outaddr(resizer, buffer->iss_addr); - - /* - * If streaming was enabled before there was a buffer queued - * or underrun happened in the ISR, the hardware was not enabled - * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set. - * Enable it now. - */ - if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { - resizer_enable(resizer, 1); - iss_video_dmaqueue_flags_clr(video); - } - - return 0; -} - -static const struct iss_video_operations resizer_video_ops = { - .queue = resizer_video_queue, -}; - -/* ----------------------------------------------------------------------------- - * V4L2 subdev operations - */ - -/* - * resizer_set_stream - Enable/Disable streaming on the RESIZER module - * @sd: ISP RESIZER V4L2 subdevice - * @enable: Enable/disable stream - */ -static int resizer_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct iss_device *iss = to_iss_device(resizer); - struct iss_video *video_out = &resizer->video_out; - int ret = 0; - - if (resizer->state == ISS_PIPELINE_STREAM_STOPPED) { - if (enable == ISS_PIPELINE_STREAM_STOPPED) - return 0; - - omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ); - - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_MMR, - RSZ_GCK_MMR_MMR); - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_SDR, - RSZ_GCK_SDR_CORE); - - /* FIXME: Enable RSZB also */ - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SYSCONFIG, - RSZ_SYSCONFIG_RSZA_CLK_EN); - } - - switch (enable) { - case ISS_PIPELINE_STREAM_CONTINUOUS: - - resizer_configure(resizer); - resizer_print_status(resizer); - - /* - * When outputting to memory with no buffer available, let the - * buffer queue handler start the hardware. A DMA queue flag - * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is - * a buffer available. - */ - if (resizer->output & RESIZER_OUTPUT_MEMORY && - !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED)) - break; - - atomic_set(&resizer->stopping, 0); - resizer_enable(resizer, 1); - iss_video_dmaqueue_flags_clr(video_out); - break; - - case ISS_PIPELINE_STREAM_STOPPED: - if (resizer->state == ISS_PIPELINE_STREAM_STOPPED) - return 0; - if (omap4iss_module_sync_idle(&sd->entity, &resizer->wait, - &resizer->stopping)) - ret = -ETIMEDOUT; - - resizer_enable(resizer, 0); - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SYSCONFIG, - RSZ_SYSCONFIG_RSZA_CLK_EN); - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_SDR, - RSZ_GCK_SDR_CORE); - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_MMR, - RSZ_GCK_MMR_MMR); - omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ); - iss_video_dmaqueue_flags_clr(video_out); - break; - } - - resizer->state = enable; - return ret; -} - -static struct v4l2_mbus_framefmt * -__resizer_get_format(struct iss_resizer_device *resizer, - struct v4l2_subdev_state *sd_state, unsigned int pad, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_state_get_format(sd_state, pad); - return &resizer->formats[pad]; -} - -/* - * resizer_try_format - Try video format on a pad - * @resizer: ISS RESIZER device - * @sd_state: V4L2 subdev state - * @pad: Pad number - * @fmt: Format - */ -static void -resizer_try_format(struct iss_resizer_device *resizer, - struct v4l2_subdev_state *sd_state, unsigned int pad, - struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) -{ - u32 pixelcode; - struct v4l2_mbus_framefmt *format; - unsigned int width = fmt->width; - unsigned int height = fmt->height; - unsigned int i; - - switch (pad) { - case RESIZER_PAD_SINK: - for (i = 0; i < ARRAY_SIZE(resizer_fmts); i++) { - if (fmt->code == resizer_fmts[i]) - break; - } - - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(resizer_fmts)) - fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; - - /* Clamp the input size. */ - fmt->width = clamp_t(u32, width, 1, 8192); - fmt->height = clamp_t(u32, height, 1, 8192); - break; - - case RESIZER_PAD_SOURCE_MEM: - pixelcode = fmt->code; - format = __resizer_get_format(resizer, sd_state, - RESIZER_PAD_SINK, - which); - memcpy(fmt, format, sizeof(*fmt)); - - if ((pixelcode == MEDIA_BUS_FMT_YUYV8_1_5X8) && - (fmt->code == MEDIA_BUS_FMT_UYVY8_1X16)) - fmt->code = pixelcode; - - /* The data formatter truncates the number of horizontal output - * pixels to a multiple of 16. To avoid clipping data, allow - * callers to request an output size bigger than the input size - * up to the nearest multiple of 16. - */ - fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15); - fmt->width &= ~15; - fmt->height = clamp_t(u32, height, 32, fmt->height); - break; - } - - fmt->colorspace = V4L2_COLORSPACE_JPEG; - fmt->field = V4L2_FIELD_NONE; -} - -/* - * resizer_enum_mbus_code - Handle pixel format enumeration - * @sd : pointer to v4l2 subdev structure - * @sd_state: V4L2 subdev state - * @code : pointer to v4l2_subdev_mbus_code_enum structure - * return -EINVAL or zero on success - */ -static int resizer_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - switch (code->pad) { - case RESIZER_PAD_SINK: - if (code->index >= ARRAY_SIZE(resizer_fmts)) - return -EINVAL; - - code->code = resizer_fmts[code->index]; - break; - - case RESIZER_PAD_SOURCE_MEM: - format = __resizer_get_format(resizer, sd_state, - RESIZER_PAD_SINK, - code->which); - - if (code->index == 0) { - code->code = format->code; - break; - } - - switch (format->code) { - case MEDIA_BUS_FMT_UYVY8_1X16: - if (code->index == 1) - code->code = MEDIA_BUS_FMT_YUYV8_1_5X8; - else - return -EINVAL; - break; - default: - if (code->index != 0) - return -EINVAL; - } - - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int resizer_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt format; - - if (fse->index != 0) - return -EINVAL; - - format.code = fse->code; - format.width = 1; - format.height = 1; - resizer_try_format(resizer, sd_state, fse->pad, &format, fse->which); - fse->min_width = format.width; - fse->min_height = format.height; - - if (format.code != fse->code) - return -EINVAL; - - format.code = fse->code; - format.width = -1; - format.height = -1; - resizer_try_format(resizer, sd_state, fse->pad, &format, fse->which); - fse->max_width = format.width; - fse->max_height = format.height; - - return 0; -} - -/* - * resizer_get_format - Retrieve the video format on a pad - * @sd : ISP RESIZER V4L2 subdevice - * @sd_state: V4L2 subdev state - * @fmt: Format - * - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond - * to the format type. - */ -static int resizer_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __resizer_get_format(resizer, sd_state, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - fmt->format = *format; - return 0; -} - -/* - * resizer_set_format - Set the video format on a pad - * @sd : ISP RESIZER V4L2 subdevice - * @sd_state: V4L2 subdev state - * @fmt: Format - * - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond - * to the format type. - */ -static int resizer_set_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __resizer_get_format(resizer, sd_state, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - resizer_try_format(resizer, sd_state, fmt->pad, &fmt->format, - fmt->which); - *format = fmt->format; - - /* Propagate the format from sink to source */ - if (fmt->pad == RESIZER_PAD_SINK) { - format = __resizer_get_format(resizer, sd_state, - RESIZER_PAD_SOURCE_MEM, - fmt->which); - *format = fmt->format; - resizer_try_format(resizer, sd_state, RESIZER_PAD_SOURCE_MEM, - format, - fmt->which); - } - - return 0; -} - -static int resizer_link_validate(struct v4l2_subdev *sd, - struct media_link *link, - struct v4l2_subdev_format *source_fmt, - struct v4l2_subdev_format *sink_fmt) -{ - /* Check if the two ends match */ - if (source_fmt->format.width != sink_fmt->format.width || - source_fmt->format.height != sink_fmt->format.height) - return -EPIPE; - - if (source_fmt->format.code != sink_fmt->format.code) - return -EPIPE; - - return 0; -} - -/* - * resizer_init_formats - Initialize formats on all pads - * @sd: ISP RESIZER V4L2 subdevice - * @fh: V4L2 subdev file handle - * - * Initialize all pad formats with default values. If fh is not NULL, try - * formats are initialized on the file handle. Otherwise active formats are - * initialized on the device. - */ -static int resizer_init_formats(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct v4l2_subdev_format format; - - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_PAD_SINK; - format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; - format.format.code = MEDIA_BUS_FMT_UYVY8_1X16; - format.format.width = 4096; - format.format.height = 4096; - resizer_set_format(sd, fh ? fh->state : NULL, &format); - - return 0; -} - -/* V4L2 subdev video operations */ -static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = { - .s_stream = resizer_set_stream, -}; - -/* V4L2 subdev pad operations */ -static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = { - .enum_mbus_code = resizer_enum_mbus_code, - .enum_frame_size = resizer_enum_frame_size, - .get_fmt = resizer_get_format, - .set_fmt = resizer_set_format, - .link_validate = resizer_link_validate, -}; - -/* V4L2 subdev operations */ -static const struct v4l2_subdev_ops resizer_v4l2_ops = { - .video = &resizer_v4l2_video_ops, - .pad = &resizer_v4l2_pad_ops, -}; - -/* V4L2 subdev internal operations */ -static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = { - .open = resizer_init_formats, -}; - -/* ----------------------------------------------------------------------------- - * Media entity operations - */ - -/* - * resizer_link_setup - Setup RESIZER connections - * @entity: RESIZER media entity - * @local: Pad at the local end of the link - * @remote: Pad at the remote end of the link - * @flags: Link flags - * - * return -EINVAL or zero on success - */ -static int resizer_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct iss_device *iss = to_iss_device(resizer); - unsigned int index = local->index; - - /* FIXME: this is actually a hack! */ - if (is_media_entity_v4l2_subdev(remote->entity)) - index |= 2 << 16; - - switch (index) { - case RESIZER_PAD_SINK | 2 << 16: - /* Read from IPIPE or IPIPEIF. */ - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->input = RESIZER_INPUT_NONE; - break; - } - - if (resizer->input != RESIZER_INPUT_NONE) - return -EBUSY; - - if (remote->entity == &iss->ipipeif.subdev.entity) - resizer->input = RESIZER_INPUT_IPIPEIF; - else if (remote->entity == &iss->ipipe.subdev.entity) - resizer->input = RESIZER_INPUT_IPIPE; - - break; - - case RESIZER_PAD_SOURCE_MEM: - /* Write to memory */ - if (flags & MEDIA_LNK_FL_ENABLED) { - if (resizer->output & ~RESIZER_OUTPUT_MEMORY) - return -EBUSY; - resizer->output |= RESIZER_OUTPUT_MEMORY; - } else { - resizer->output &= ~RESIZER_OUTPUT_MEMORY; - } - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* media operations */ -static const struct media_entity_operations resizer_media_ops = { - .link_setup = resizer_link_setup, - .link_validate = v4l2_subdev_link_validate, -}; - -/* - * resizer_init_entities - Initialize V4L2 subdev and media entity - * @resizer: ISS ISP RESIZER module - * - * Return 0 on success and a negative error code on failure. - */ -static int resizer_init_entities(struct iss_resizer_device *resizer) -{ - struct v4l2_subdev *sd = &resizer->subdev; - struct media_pad *pads = resizer->pads; - struct media_entity *me = &sd->entity; - int ret; - - resizer->input = RESIZER_INPUT_NONE; - - v4l2_subdev_init(sd, &resizer_v4l2_ops); - sd->internal_ops = &resizer_v4l2_internal_ops; - strscpy(sd->name, "OMAP4 ISS ISP resizer", sizeof(sd->name)); - sd->grp_id = BIT(16); /* group ID for iss subdevs */ - v4l2_set_subdevdata(sd, resizer); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[RESIZER_PAD_SOURCE_MEM].flags = MEDIA_PAD_FL_SOURCE; - - me->ops = &resizer_media_ops; - ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads); - if (ret < 0) - return ret; - - resizer_init_formats(sd, NULL); - - resizer->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - resizer->video_out.ops = &resizer_video_ops; - resizer->video_out.iss = to_iss_device(resizer); - resizer->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; - resizer->video_out.bpl_alignment = 32; - resizer->video_out.bpl_zero_padding = 1; - resizer->video_out.bpl_max = 0x1ffe0; - - return omap4iss_video_init(&resizer->video_out, "ISP resizer a"); -} - -void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer) -{ - v4l2_device_unregister_subdev(&resizer->subdev); - omap4iss_video_unregister(&resizer->video_out); -} - -int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer, - struct v4l2_device *vdev) -{ - int ret; - - /* Register the subdev and video node. */ - ret = v4l2_device_register_subdev(vdev, &resizer->subdev); - if (ret < 0) - goto error; - - ret = omap4iss_video_register(&resizer->video_out, vdev); - if (ret < 0) - goto error; - - return 0; - -error: - omap4iss_resizer_unregister_entities(resizer); - return ret; -} - -/* ----------------------------------------------------------------------------- - * ISP RESIZER initialisation and cleanup - */ - -/* - * omap4iss_resizer_init - RESIZER module initialization. - * @iss: Device pointer specific to the OMAP4 ISS. - * - * TODO: Get the initialisation values from platform data. - * - * Return 0 on success or a negative error code otherwise. - */ -int omap4iss_resizer_init(struct iss_device *iss) -{ - struct iss_resizer_device *resizer = &iss->resizer; - - resizer->state = ISS_PIPELINE_STREAM_STOPPED; - init_waitqueue_head(&resizer->wait); - - return resizer_init_entities(resizer); -} - -/* - * omap4iss_resizer_create_links() - RESIZER pads links creation - * @iss: Pointer to ISS device - * - * return negative error code or zero on success - */ -int omap4iss_resizer_create_links(struct iss_device *iss) -{ - struct iss_resizer_device *resizer = &iss->resizer; - - /* Connect the RESIZER subdev to the video node. */ - return media_create_pad_link(&resizer->subdev.entity, - RESIZER_PAD_SOURCE_MEM, - &resizer->video_out.video.entity, 0, 0); -} - -/* - * omap4iss_resizer_cleanup - RESIZER module cleanup. - * @iss: Device pointer specific to the OMAP4 ISS. - */ -void omap4iss_resizer_cleanup(struct iss_device *iss) -{ - struct iss_resizer_device *resizer = &iss->resizer; - - media_entity_cleanup(&resizer->subdev.entity); -} diff --git a/drivers/staging/media/omap4iss/iss_resizer.h b/drivers/staging/media/omap4iss/iss_resizer.h deleted file mode 100644 index cb937fccc21f..000000000000 --- a/drivers/staging/media/omap4iss/iss_resizer.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * TI OMAP4 ISS V4L2 Driver - ISP RESIZER module - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#ifndef OMAP4_ISS_RESIZER_H -#define OMAP4_ISS_RESIZER_H - -#include "iss_video.h" - -enum resizer_input_entity { - RESIZER_INPUT_NONE, - RESIZER_INPUT_IPIPE, - RESIZER_INPUT_IPIPEIF -}; - -#define RESIZER_OUTPUT_MEMORY BIT(0) - -/* Sink and source RESIZER pads */ -#define RESIZER_PAD_SINK 0 -#define RESIZER_PAD_SOURCE_MEM 1 -#define RESIZER_PADS_NUM 2 - -/* - * struct iss_resizer_device - Structure for the RESIZER module to store its own - * information - * @subdev: V4L2 subdevice - * @pads: Sink and source media entity pads - * @formats: Active video formats - * @input: Active input - * @output: Active outputs - * @video_out: Output video node - * @error: A hardware error occurred during capture - * @state: Streaming state - * @wait: Wait queue used to stop the module - * @stopping: Stopping state - */ -struct iss_resizer_device { - struct v4l2_subdev subdev; - struct media_pad pads[RESIZER_PADS_NUM]; - struct v4l2_mbus_framefmt formats[RESIZER_PADS_NUM]; - - enum resizer_input_entity input; - unsigned int output; - struct iss_video video_out; - unsigned int error; - - enum iss_pipeline_stream_state state; - wait_queue_head_t wait; - atomic_t stopping; -}; - -struct iss_device; - -int omap4iss_resizer_init(struct iss_device *iss); -int omap4iss_resizer_create_links(struct iss_device *iss); -void omap4iss_resizer_cleanup(struct iss_device *iss); -int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer, - struct v4l2_device *vdev); -void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer); - -int omap4iss_resizer_busy(struct iss_resizer_device *resizer); -void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events); -void omap4iss_resizer_restore_context(struct iss_device *iss); -void omap4iss_resizer_max_rate(struct iss_resizer_device *resizer, - unsigned int *max_rate); - -#endif /* OMAP4_ISS_RESIZER_H */ diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c deleted file mode 100644 index 22fa4d6cae10..000000000000 --- a/drivers/staging/media/omap4iss/iss_video.c +++ /dev/null @@ -1,1274 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * TI OMAP4 ISS V4L2 Driver - Generic video node - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "iss_video.h" -#include "iss.h" - -/* ----------------------------------------------------------------------------- - * Helper functions - */ - -static struct iss_format_info formats[] = { - { MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8, - MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8, - V4L2_PIX_FMT_GREY, 8, }, - { MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y10_1X10, - MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y8_1X8, - V4L2_PIX_FMT_Y10, 10, }, - { MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y10_1X10, - MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y8_1X8, - V4L2_PIX_FMT_Y12, 12, }, - { MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8, - MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR8, 8, }, - { MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, - MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG8, 8, }, - { MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8, - MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG8, 8, }, - { MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8, - MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB8, 8, }, - { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, - MEDIA_BUS_FMT_SGRBG10_1X10, 0, - V4L2_PIX_FMT_SGRBG10DPCM8, 8, }, - { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, - MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR10, 10, }, - { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10, - MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG10, 10, }, - { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, - MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG10, 10, }, - { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10, - MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB10, 10, }, - { MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR10_1X10, - MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR12, 12, }, - { MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG10_1X10, - MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG12, 12, }, - { MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG10_1X10, - MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG12, 12, }, - { MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB10_1X10, - MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB12, 12, }, - { MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_UYVY8_1X16, - MEDIA_BUS_FMT_UYVY8_1X16, 0, - V4L2_PIX_FMT_UYVY, 16, }, - { MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YUYV8_1X16, - MEDIA_BUS_FMT_YUYV8_1X16, 0, - V4L2_PIX_FMT_YUYV, 16, }, - { MEDIA_BUS_FMT_YUYV8_1_5X8, MEDIA_BUS_FMT_YUYV8_1_5X8, - MEDIA_BUS_FMT_YUYV8_1_5X8, 0, - V4L2_PIX_FMT_NV12, 8, }, -}; - -const struct iss_format_info * -omap4iss_video_format_info(u32 code) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(formats); ++i) { - if (formats[i].code == code) - return &formats[i]; - } - - return NULL; -} - -/* - * iss_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format - * @video: ISS video instance - * @mbus: v4l2_mbus_framefmt format (input) - * @pix: v4l2_pix_format format (output) - * - * Fill the output pix structure with information from the input mbus format. - * The bytesperline and sizeimage fields are computed from the requested bytes - * per line value in the pix format and information from the video instance. - * - * Return the number of padding bytes at end of line. - */ -static unsigned int iss_video_mbus_to_pix(const struct iss_video *video, - const struct v4l2_mbus_framefmt *mbus, - struct v4l2_pix_format *pix) -{ - unsigned int bpl = pix->bytesperline; - unsigned int min_bpl; - unsigned int i; - - memset(pix, 0, sizeof(*pix)); - pix->width = mbus->width; - pix->height = mbus->height; - - /* - * Skip the last format in the loop so that it will be selected if no - * match is found. - */ - for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) { - if (formats[i].code == mbus->code) - break; - } - - min_bpl = pix->width * ALIGN(formats[i].bpp, 8) / 8; - - /* - * Clamp the requested bytes per line value. If the maximum bytes per - * line value is zero, the module doesn't support user configurable line - * sizes. Override the requested value with the minimum in that case. - */ - if (video->bpl_max) - bpl = clamp(bpl, min_bpl, video->bpl_max); - else - bpl = min_bpl; - - if (!video->bpl_zero_padding || bpl != min_bpl) - bpl = ALIGN(bpl, video->bpl_alignment); - - pix->pixelformat = formats[i].pixelformat; - pix->bytesperline = bpl; - pix->sizeimage = pix->bytesperline * pix->height; - pix->colorspace = mbus->colorspace; - pix->field = mbus->field; - - /* FIXME: Special case for NV12! We should make this nicer... */ - if (pix->pixelformat == V4L2_PIX_FMT_NV12) - pix->sizeimage += (pix->bytesperline * pix->height) / 2; - - return bpl - min_bpl; -} - -static void iss_video_pix_to_mbus(const struct v4l2_pix_format *pix, - struct v4l2_mbus_framefmt *mbus) -{ - unsigned int i; - - memset(mbus, 0, sizeof(*mbus)); - mbus->width = pix->width; - mbus->height = pix->height; - - /* - * Skip the last format in the loop so that it will be selected if no - * match is found. - */ - for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) { - if (formats[i].pixelformat == pix->pixelformat) - break; - } - - mbus->code = formats[i].code; - mbus->colorspace = pix->colorspace; - mbus->field = pix->field; -} - -static struct v4l2_subdev * -iss_video_remote_subdev(struct iss_video *video, u32 *pad) -{ - struct media_pad *remote; - - remote = media_pad_remote_pad_first(&video->pad); - - if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) - return NULL; - - if (pad) - *pad = remote->index; - - return media_entity_to_v4l2_subdev(remote->entity); -} - -/* Return a pointer to the ISS video instance at the far end of the pipeline. */ -static struct iss_video * -iss_video_far_end(struct iss_video *video, struct iss_pipeline *pipe) -{ - struct media_pipeline_entity_iter iter; - struct media_entity *entity; - struct iss_video *far_end = NULL; - int ret; - - ret = media_pipeline_entity_iter_init(&pipe->pipe, &iter); - if (ret) - return ERR_PTR(-ENOMEM); - - media_pipeline_for_each_entity(&pipe->pipe, &iter, entity) { - struct iss_video *other; - - if (entity == &video->video.entity) - continue; - - if (!is_media_entity_v4l2_video_device(entity)) - continue; - - other = to_iss_video(media_entity_to_video_device(entity)); - if (other->type != video->type) { - far_end = other; - break; - } - } - - media_pipeline_entity_iter_cleanup(&iter); - - return far_end; -} - -static int -__iss_video_get_format(struct iss_video *video, - struct v4l2_mbus_framefmt *format) -{ - struct v4l2_subdev_format fmt = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct v4l2_subdev *subdev; - u32 pad; - int ret; - - subdev = iss_video_remote_subdev(video, &pad); - if (!subdev) - return -EINVAL; - - fmt.pad = pad; - - mutex_lock(&video->mutex); - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); - mutex_unlock(&video->mutex); - - if (ret) - return ret; - - *format = fmt.format; - return 0; -} - -static int -iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh) -{ - struct v4l2_mbus_framefmt format; - struct v4l2_pix_format pixfmt; - int ret; - - ret = __iss_video_get_format(video, &format); - if (ret < 0) - return ret; - - pixfmt.bytesperline = 0; - ret = iss_video_mbus_to_pix(video, &format, &pixfmt); - - if (vfh->format.fmt.pix.pixelformat != pixfmt.pixelformat || - vfh->format.fmt.pix.height != pixfmt.height || - vfh->format.fmt.pix.width != pixfmt.width || - vfh->format.fmt.pix.bytesperline != pixfmt.bytesperline || - vfh->format.fmt.pix.sizeimage != pixfmt.sizeimage) - return -EINVAL; - - return ret; -} - -/* ----------------------------------------------------------------------------- - * Video queue operations - */ - -static int iss_video_queue_setup(struct vb2_queue *vq, - unsigned int *count, unsigned int *num_planes, - unsigned int sizes[], - struct device *alloc_devs[]) -{ - struct iss_video_fh *vfh = vb2_get_drv_priv(vq); - struct iss_video *video = vfh->video; - - /* Revisit multi-planar support for NV12 */ - *num_planes = 1; - - sizes[0] = vfh->format.fmt.pix.sizeimage; - if (sizes[0] == 0) - return -EINVAL; - - *count = min(*count, video->capture_mem / PAGE_ALIGN(sizes[0])); - - return 0; -} - -static void iss_video_buf_cleanup(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb); - - if (buffer->iss_addr) - buffer->iss_addr = 0; -} - -static int iss_video_buf_prepare(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue); - struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb); - struct iss_video *video = vfh->video; - unsigned long size = vfh->format.fmt.pix.sizeimage; - dma_addr_t addr; - - if (vb2_plane_size(vb, 0) < size) - return -ENOBUFS; - - addr = vb2_dma_contig_plane_dma_addr(vb, 0); - if (!IS_ALIGNED(addr, 32)) { - dev_dbg(video->iss->dev, - "Buffer address must be aligned to 32 bytes boundary.\n"); - return -EINVAL; - } - - vb2_set_plane_payload(vb, 0, size); - buffer->iss_addr = addr; - return 0; -} - -static void iss_video_buf_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue); - struct iss_video *video = vfh->video; - struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb); - struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity); - unsigned long flags; - bool empty; - - spin_lock_irqsave(&video->qlock, flags); - - /* - * Mark the buffer is faulty and give it back to the queue immediately - * if the video node has registered an error. vb2 will perform the same - * check when preparing the buffer, but that is inherently racy, so we - * need to handle the race condition with an authoritative check here. - */ - if (unlikely(video->error)) { - vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); - spin_unlock_irqrestore(&video->qlock, flags); - return; - } - - empty = list_empty(&video->dmaqueue); - list_add_tail(&buffer->list, &video->dmaqueue); - - spin_unlock_irqrestore(&video->qlock, flags); - - if (empty) { - enum iss_pipeline_state state; - unsigned int start; - - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - state = ISS_PIPELINE_QUEUE_OUTPUT; - else - state = ISS_PIPELINE_QUEUE_INPUT; - - spin_lock_irqsave(&pipe->lock, flags); - pipe->state |= state; - video->ops->queue(video, buffer); - video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_QUEUED; - - start = iss_pipeline_ready(pipe); - if (start) - pipe->state |= ISS_PIPELINE_STREAM; - spin_unlock_irqrestore(&pipe->lock, flags); - - if (start) - omap4iss_pipeline_set_stream(pipe, - ISS_PIPELINE_STREAM_SINGLESHOT); - } -} - -static const struct vb2_ops iss_video_vb2ops = { - .queue_setup = iss_video_queue_setup, - .buf_prepare = iss_video_buf_prepare, - .buf_queue = iss_video_buf_queue, - .buf_cleanup = iss_video_buf_cleanup, -}; - -/* - * omap4iss_video_buffer_next - Complete the current buffer and return the next - * @video: ISS video object - * - * Remove the current video buffer from the DMA queue and fill its timestamp, - * field count and state fields before waking up its completion handler. - * - * For capture video nodes, the buffer state is set to VB2_BUF_STATE_DONE if no - * error has been flagged in the pipeline, or to VB2_BUF_STATE_ERROR otherwise. - * - * The DMA queue is expected to contain at least one buffer. - * - * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is - * empty. - */ -struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video) -{ - struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity); - enum iss_pipeline_state state; - struct iss_buffer *buf; - unsigned long flags; - - spin_lock_irqsave(&video->qlock, flags); - if (WARN_ON(list_empty(&video->dmaqueue))) { - spin_unlock_irqrestore(&video->qlock, flags); - return NULL; - } - - buf = list_first_entry(&video->dmaqueue, struct iss_buffer, - list); - list_del(&buf->list); - spin_unlock_irqrestore(&video->qlock, flags); - - buf->vb.vb2_buf.timestamp = ktime_get_ns(); - - /* - * Do frame number propagation only if this is the output video node. - * Frame number either comes from the CSI receivers or it gets - * incremented here if H3A is not active. - * Note: There is no guarantee that the output buffer will finish - * first, so the input number might lag behind by 1 in some cases. - */ - if (video == pipe->output && !pipe->do_propagation) - buf->vb.sequence = - atomic_inc_return(&pipe->frame_number); - else - buf->vb.sequence = atomic_read(&pipe->frame_number); - - vb2_buffer_done(&buf->vb.vb2_buf, pipe->error ? - VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); - pipe->error = false; - - spin_lock_irqsave(&video->qlock, flags); - if (list_empty(&video->dmaqueue)) { - spin_unlock_irqrestore(&video->qlock, flags); - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - state = ISS_PIPELINE_QUEUE_OUTPUT - | ISS_PIPELINE_STREAM; - else - state = ISS_PIPELINE_QUEUE_INPUT - | ISS_PIPELINE_STREAM; - - spin_lock_irqsave(&pipe->lock, flags); - pipe->state &= ~state; - if (video->pipe.stream_state == ISS_PIPELINE_STREAM_CONTINUOUS) - video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_UNDERRUN; - spin_unlock_irqrestore(&pipe->lock, flags); - return NULL; - } - - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input) { - spin_lock(&pipe->lock); - pipe->state &= ~ISS_PIPELINE_STREAM; - spin_unlock(&pipe->lock); - } - - buf = list_first_entry(&video->dmaqueue, struct iss_buffer, - list); - spin_unlock_irqrestore(&video->qlock, flags); - buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; - return buf; -} - -/* - * omap4iss_video_cancel_stream - Cancel stream on a video node - * @video: ISS video object - * - * Cancelling a stream mark all buffers on the video node as erroneous and makes - * sure no new buffer can be queued. - */ -void omap4iss_video_cancel_stream(struct iss_video *video) -{ - unsigned long flags; - - spin_lock_irqsave(&video->qlock, flags); - - while (!list_empty(&video->dmaqueue)) { - struct iss_buffer *buf; - - buf = list_first_entry(&video->dmaqueue, struct iss_buffer, - list); - list_del(&buf->list); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } - - vb2_queue_error(video->queue); - video->error = true; - - spin_unlock_irqrestore(&video->qlock, flags); -} - -/* ----------------------------------------------------------------------------- - * V4L2 ioctls - */ - -static int -iss_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) -{ - struct iss_video *video = video_drvdata(file); - - strscpy(cap->driver, ISS_VIDEO_DRIVER_NAME, sizeof(cap->driver)); - strscpy(cap->card, video->video.name, sizeof(cap->card)); - strscpy(cap->bus_info, "media", sizeof(cap->bus_info)); - cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING - | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT; - - return 0; -} - -static int -iss_video_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) -{ - struct iss_video *video = video_drvdata(file); - struct v4l2_mbus_framefmt format; - unsigned int index = f->index; - unsigned int i; - int ret; - - if (f->type != video->type) - return -EINVAL; - - ret = __iss_video_get_format(video, &format); - if (ret < 0) - return ret; - - for (i = 0; i < ARRAY_SIZE(formats); ++i) { - const struct iss_format_info *info = &formats[i]; - - if (format.code != info->code) - continue; - - if (index == 0) { - f->pixelformat = info->pixelformat; - return 0; - } - - index--; - } - - return -EINVAL; -} - -static int -iss_video_get_format(struct file *file, void *fh, struct v4l2_format *format) -{ - struct iss_video_fh *vfh = to_iss_video_fh(fh); - struct iss_video *video = video_drvdata(file); - - if (format->type != video->type) - return -EINVAL; - - mutex_lock(&video->mutex); - *format = vfh->format; - mutex_unlock(&video->mutex); - - return 0; -} - -static int -iss_video_set_format(struct file *file, void *fh, struct v4l2_format *format) -{ - struct iss_video_fh *vfh = to_iss_video_fh(fh); - struct iss_video *video = video_drvdata(file); - struct v4l2_mbus_framefmt fmt; - - if (format->type != video->type) - return -EINVAL; - - mutex_lock(&video->mutex); - - /* - * Fill the bytesperline and sizeimage fields by converting to media bus - * format and back to pixel format. - */ - iss_video_pix_to_mbus(&format->fmt.pix, &fmt); - iss_video_mbus_to_pix(video, &fmt, &format->fmt.pix); - - vfh->format = *format; - - mutex_unlock(&video->mutex); - return 0; -} - -static int -iss_video_try_format(struct file *file, void *fh, struct v4l2_format *format) -{ - struct iss_video *video = video_drvdata(file); - struct v4l2_subdev_format fmt = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct v4l2_subdev *subdev; - u32 pad; - int ret; - - if (format->type != video->type) - return -EINVAL; - - subdev = iss_video_remote_subdev(video, &pad); - if (!subdev) - return -EINVAL; - - iss_video_pix_to_mbus(&format->fmt.pix, &fmt.format); - - fmt.pad = pad; - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); - if (ret) - return ret; - - iss_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix); - return 0; -} - -static int -iss_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel) -{ - struct iss_video *video = video_drvdata(file); - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct v4l2_subdev *subdev; - struct v4l2_subdev_selection sdsel = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - .target = sel->target, - }; - u32 pad; - int ret; - - switch (sel->target) { - case V4L2_SEL_TGT_CROP: - case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: - if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - return -EINVAL; - break; - case V4L2_SEL_TGT_COMPOSE: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - break; - default: - return -EINVAL; - } - subdev = iss_video_remote_subdev(video, &pad); - if (!subdev) - return -EINVAL; - - /* - * Try the get selection operation first and fallback to get format if - * not implemented. - */ - sdsel.pad = pad; - ret = v4l2_subdev_call(subdev, pad, get_selection, NULL, &sdsel); - if (!ret) - sel->r = sdsel.r; - if (ret != -ENOIOCTLCMD) - return ret; - - format.pad = pad; - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format); - if (ret < 0) - return ret == -ENOIOCTLCMD ? -ENOTTY : ret; - - sel->r.left = 0; - sel->r.top = 0; - sel->r.width = format.format.width; - sel->r.height = format.format.height; - - return 0; -} - -static int -iss_video_set_selection(struct file *file, void *fh, struct v4l2_selection *sel) -{ - struct iss_video *video = video_drvdata(file); - struct v4l2_subdev *subdev; - struct v4l2_subdev_selection sdsel = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - .target = sel->target, - .flags = sel->flags, - .r = sel->r, - }; - u32 pad; - int ret; - - switch (sel->target) { - case V4L2_SEL_TGT_CROP: - if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - return -EINVAL; - break; - case V4L2_SEL_TGT_COMPOSE: - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - break; - default: - return -EINVAL; - } - subdev = iss_video_remote_subdev(video, &pad); - if (!subdev) - return -EINVAL; - - sdsel.pad = pad; - mutex_lock(&video->mutex); - ret = v4l2_subdev_call(subdev, pad, set_selection, NULL, &sdsel); - mutex_unlock(&video->mutex); - if (!ret) - sel->r = sdsel.r; - - return ret == -ENOIOCTLCMD ? -ENOTTY : ret; -} - -static int -iss_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a) -{ - struct iss_video_fh *vfh = to_iss_video_fh(fh); - struct iss_video *video = video_drvdata(file); - - if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || - video->type != a->type) - return -EINVAL; - - memset(a, 0, sizeof(*a)); - a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - a->parm.output.capability = V4L2_CAP_TIMEPERFRAME; - a->parm.output.timeperframe = vfh->timeperframe; - - return 0; -} - -static int -iss_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a) -{ - struct iss_video_fh *vfh = to_iss_video_fh(fh); - struct iss_video *video = video_drvdata(file); - - if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || - video->type != a->type) - return -EINVAL; - - if (a->parm.output.timeperframe.denominator == 0) - a->parm.output.timeperframe.denominator = 1; - - vfh->timeperframe = a->parm.output.timeperframe; - - return 0; -} - -static int -iss_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb) -{ - struct iss_video_fh *vfh = to_iss_video_fh(fh); - - return vb2_reqbufs(&vfh->queue, rb); -} - -static int -iss_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) -{ - struct iss_video_fh *vfh = to_iss_video_fh(fh); - - return vb2_querybuf(&vfh->queue, b); -} - -static int -iss_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) -{ - struct iss_video *video = video_drvdata(file); - struct iss_video_fh *vfh = to_iss_video_fh(fh); - - return vb2_qbuf(&vfh->queue, video->video.v4l2_dev->mdev, b); -} - -static int -iss_video_expbuf(struct file *file, void *fh, struct v4l2_exportbuffer *e) -{ - struct iss_video_fh *vfh = to_iss_video_fh(fh); - - return vb2_expbuf(&vfh->queue, e); -} - -static int -iss_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) -{ - struct iss_video_fh *vfh = to_iss_video_fh(fh); - - return vb2_dqbuf(&vfh->queue, b, file->f_flags & O_NONBLOCK); -} - -/* - * Stream management - * - * Every ISS pipeline has a single input and a single output. The input can be - * either a sensor or a video node. The output is always a video node. - * - * As every pipeline has an output video node, the ISS video objects at the - * pipeline output stores the pipeline state. It tracks the streaming state of - * both the input and output, as well as the availability of buffers. - * - * In sensor-to-memory mode, frames are always available at the pipeline input. - * Starting the sensor usually requires I2C transfers and must be done in - * interruptible context. The pipeline is started and stopped synchronously - * to the stream on/off commands. All modules in the pipeline will get their - * subdev set stream handler called. The module at the end of the pipeline must - * delay starting the hardware until buffers are available at its output. - * - * In memory-to-memory mode, starting/stopping the stream requires - * synchronization between the input and output. ISS modules can't be stopped - * in the middle of a frame, and at least some of the modules seem to become - * busy as soon as they're started, even if they don't receive a frame start - * event. For that reason frames need to be processed in single-shot mode. The - * driver needs to wait until a frame is completely processed and written to - * memory before restarting the pipeline for the next frame. Pipelined - * processing might be possible but requires more testing. - * - * Stream start must be delayed until buffers are available at both the input - * and output. The pipeline must be started in the vb2 queue callback with - * the buffers queue spinlock held. The modules subdev set stream operation must - * not sleep. - */ -static int -iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) -{ - struct iss_video_fh *vfh = to_iss_video_fh(fh); - struct iss_video *video = video_drvdata(file); - struct media_device *mdev = video->video.entity.graph_obj.mdev; - struct media_pipeline_pad_iter iter; - enum iss_pipeline_state state; - struct iss_pipeline *pipe; - struct iss_video *far_end; - struct media_pad *pad; - unsigned long flags; - int ret; - - if (type != video->type) - return -EINVAL; - - mutex_lock(&video->stream_lock); - - /* - * Start streaming on the pipeline. No link touching an entity in the - * pipeline can be activated or deactivated once streaming is started. - */ - pipe = to_iss_pipeline(&video->video.entity) ? : &video->pipe; - pipe->external = NULL; - pipe->external_rate = 0; - pipe->external_bpp = 0; - - ret = media_entity_enum_init(&pipe->ent_enum, mdev); - if (ret) - goto err_entity_enum_init; - - if (video->iss->pdata->set_constraints) - video->iss->pdata->set_constraints(video->iss, true); - - ret = video_device_pipeline_start(&video->video, &pipe->pipe); - if (ret < 0) - goto err_media_pipeline_start; - - media_pipeline_for_each_pad(&pipe->pipe, &iter, pad) - media_entity_enum_set(&pipe->ent_enum, pad->entity); - - /* - * Verify that the currently configured format matches the output of - * the connected subdev. - */ - ret = iss_video_check_format(video, vfh); - if (ret < 0) - goto err_iss_video_check_format; - - video->bpl_padding = ret; - video->bpl_value = vfh->format.fmt.pix.bytesperline; - - /* - * Find the ISS video node connected at the far end of the pipeline and - * update the pipeline. - */ - far_end = iss_video_far_end(video, pipe); - if (IS_ERR(far_end)) { - ret = PTR_ERR(far_end); - goto err_iss_video_check_format; - } - - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - state = ISS_PIPELINE_STREAM_OUTPUT | ISS_PIPELINE_IDLE_OUTPUT; - pipe->input = far_end; - pipe->output = video; - } else { - if (!far_end) { - ret = -EPIPE; - goto err_iss_video_check_format; - } - - state = ISS_PIPELINE_STREAM_INPUT | ISS_PIPELINE_IDLE_INPUT; - pipe->input = video; - pipe->output = far_end; - } - - spin_lock_irqsave(&pipe->lock, flags); - pipe->state &= ~ISS_PIPELINE_STREAM; - pipe->state |= state; - spin_unlock_irqrestore(&pipe->lock, flags); - - /* - * Set the maximum time per frame as the value requested by userspace. - * This is a soft limit that can be overridden if the hardware doesn't - * support the request limit. - */ - if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - pipe->max_timeperframe = vfh->timeperframe; - - video->queue = &vfh->queue; - INIT_LIST_HEAD(&video->dmaqueue); - video->error = false; - atomic_set(&pipe->frame_number, -1); - - ret = vb2_streamon(&vfh->queue, type); - if (ret < 0) - goto err_iss_video_check_format; - - /* - * In sensor-to-memory mode, the stream can be started synchronously - * to the stream on command. In memory-to-memory mode, it will be - * started when buffers are queued on both the input and output. - */ - if (!pipe->input) { - unsigned long flags; - - ret = omap4iss_pipeline_set_stream(pipe, - ISS_PIPELINE_STREAM_CONTINUOUS); - if (ret < 0) - goto err_omap4iss_set_stream; - spin_lock_irqsave(&video->qlock, flags); - if (list_empty(&video->dmaqueue)) - video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_UNDERRUN; - spin_unlock_irqrestore(&video->qlock, flags); - } - - mutex_unlock(&video->stream_lock); - - return 0; - -err_omap4iss_set_stream: - vb2_streamoff(&vfh->queue, type); -err_iss_video_check_format: - video_device_pipeline_stop(&video->video); -err_media_pipeline_start: - if (video->iss->pdata->set_constraints) - video->iss->pdata->set_constraints(video->iss, false); - video->queue = NULL; - -err_entity_enum_init: - media_entity_enum_cleanup(&pipe->ent_enum); - - mutex_unlock(&video->stream_lock); - - return ret; -} - -static int -iss_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) -{ - struct iss_video_fh *vfh = to_iss_video_fh(fh); - struct iss_video *video = video_drvdata(file); - struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity); - enum iss_pipeline_state state; - unsigned long flags; - - if (type != video->type) - return -EINVAL; - - mutex_lock(&video->stream_lock); - - if (!vb2_is_streaming(&vfh->queue)) - goto done; - - /* Update the pipeline state. */ - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - state = ISS_PIPELINE_STREAM_OUTPUT - | ISS_PIPELINE_QUEUE_OUTPUT; - else - state = ISS_PIPELINE_STREAM_INPUT - | ISS_PIPELINE_QUEUE_INPUT; - - spin_lock_irqsave(&pipe->lock, flags); - pipe->state &= ~state; - spin_unlock_irqrestore(&pipe->lock, flags); - - /* Stop the stream. */ - omap4iss_pipeline_set_stream(pipe, ISS_PIPELINE_STREAM_STOPPED); - vb2_streamoff(&vfh->queue, type); - video->queue = NULL; - - media_entity_enum_cleanup(&pipe->ent_enum); - - if (video->iss->pdata->set_constraints) - video->iss->pdata->set_constraints(video->iss, false); - video_device_pipeline_stop(&video->video); - -done: - mutex_unlock(&video->stream_lock); - return 0; -} - -static int -iss_video_enum_input(struct file *file, void *fh, struct v4l2_input *input) -{ - if (input->index > 0) - return -EINVAL; - - strscpy(input->name, "camera", sizeof(input->name)); - input->type = V4L2_INPUT_TYPE_CAMERA; - - return 0; -} - -static int -iss_video_g_input(struct file *file, void *fh, unsigned int *input) -{ - *input = 0; - - return 0; -} - -static int -iss_video_s_input(struct file *file, void *fh, unsigned int input) -{ - return input == 0 ? 0 : -EINVAL; -} - -static const struct v4l2_ioctl_ops iss_video_ioctl_ops = { - .vidioc_querycap = iss_video_querycap, - .vidioc_enum_fmt_vid_cap = iss_video_enum_format, - .vidioc_g_fmt_vid_cap = iss_video_get_format, - .vidioc_s_fmt_vid_cap = iss_video_set_format, - .vidioc_try_fmt_vid_cap = iss_video_try_format, - .vidioc_g_fmt_vid_out = iss_video_get_format, - .vidioc_s_fmt_vid_out = iss_video_set_format, - .vidioc_try_fmt_vid_out = iss_video_try_format, - .vidioc_g_selection = iss_video_get_selection, - .vidioc_s_selection = iss_video_set_selection, - .vidioc_g_parm = iss_video_get_param, - .vidioc_s_parm = iss_video_set_param, - .vidioc_reqbufs = iss_video_reqbufs, - .vidioc_querybuf = iss_video_querybuf, - .vidioc_qbuf = iss_video_qbuf, - .vidioc_expbuf = iss_video_expbuf, - .vidioc_dqbuf = iss_video_dqbuf, - .vidioc_streamon = iss_video_streamon, - .vidioc_streamoff = iss_video_streamoff, - .vidioc_enum_input = iss_video_enum_input, - .vidioc_g_input = iss_video_g_input, - .vidioc_s_input = iss_video_s_input, -}; - -/* ----------------------------------------------------------------------------- - * V4L2 file operations - */ - -static int iss_video_open(struct file *file) -{ - struct iss_video *video = video_drvdata(file); - struct iss_video_fh *handle; - struct vb2_queue *q; - int ret = 0; - - handle = kzalloc(sizeof(*handle), GFP_KERNEL); - if (!handle) - return -ENOMEM; - - v4l2_fh_init(&handle->vfh, &video->video); - v4l2_fh_add(&handle->vfh); - - /* If this is the first user, initialise the pipeline. */ - if (!omap4iss_get(video->iss)) { - ret = -EBUSY; - goto done; - } - - ret = v4l2_pipeline_pm_get(&video->video.entity); - if (ret < 0) { - omap4iss_put(video->iss); - goto done; - } - - q = &handle->queue; - - q->type = video->type; - q->io_modes = VB2_MMAP | VB2_DMABUF; - q->drv_priv = handle; - q->ops = &iss_video_vb2ops; - q->mem_ops = &vb2_dma_contig_memops; - q->buf_struct_size = sizeof(struct iss_buffer); - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->dev = video->iss->dev; - - ret = vb2_queue_init(q); - if (ret) { - omap4iss_put(video->iss); - goto done; - } - - memset(&handle->format, 0, sizeof(handle->format)); - handle->format.type = video->type; - handle->timeperframe.denominator = 1; - - handle->video = video; - file->private_data = &handle->vfh; - -done: - if (ret < 0) { - v4l2_fh_del(&handle->vfh); - v4l2_fh_exit(&handle->vfh); - kfree(handle); - } - - return ret; -} - -static int iss_video_release(struct file *file) -{ - struct iss_video *video = video_drvdata(file); - struct v4l2_fh *vfh = file->private_data; - struct iss_video_fh *handle = to_iss_video_fh(vfh); - - /* Disable streaming and free the buffers queue resources. */ - iss_video_streamoff(file, vfh, video->type); - - v4l2_pipeline_pm_put(&video->video.entity); - - /* Release the videobuf2 queue */ - vb2_queue_release(&handle->queue); - - v4l2_fh_del(vfh); - v4l2_fh_exit(vfh); - kfree(handle); - file->private_data = NULL; - - omap4iss_put(video->iss); - - return 0; -} - -static __poll_t iss_video_poll(struct file *file, poll_table *wait) -{ - struct iss_video_fh *vfh = to_iss_video_fh(file->private_data); - - return vb2_poll(&vfh->queue, file, wait); -} - -static int iss_video_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct iss_video_fh *vfh = to_iss_video_fh(file->private_data); - - return vb2_mmap(&vfh->queue, vma); -} - -static const struct v4l2_file_operations iss_video_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = video_ioctl2, - .open = iss_video_open, - .release = iss_video_release, - .poll = iss_video_poll, - .mmap = iss_video_mmap, -}; - -/* ----------------------------------------------------------------------------- - * ISS video core - */ - -static const struct iss_video_operations iss_video_dummy_ops = { -}; - -int omap4iss_video_init(struct iss_video *video, const char *name) -{ - const char *direction; - int ret; - - switch (video->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - direction = "output"; - video->pad.flags = MEDIA_PAD_FL_SINK; - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - direction = "input"; - video->pad.flags = MEDIA_PAD_FL_SOURCE; - break; - - default: - return -EINVAL; - } - - ret = media_entity_pads_init(&video->video.entity, 1, &video->pad); - if (ret < 0) - return ret; - - spin_lock_init(&video->qlock); - mutex_init(&video->mutex); - atomic_set(&video->active, 0); - - spin_lock_init(&video->pipe.lock); - mutex_init(&video->stream_lock); - - /* Initialize the video device. */ - if (!video->ops) - video->ops = &iss_video_dummy_ops; - - video->video.fops = &iss_video_fops; - snprintf(video->video.name, sizeof(video->video.name), - "OMAP4 ISS %s %s", name, direction); - video->video.vfl_type = VFL_TYPE_VIDEO; - video->video.release = video_device_release_empty; - video->video.ioctl_ops = &iss_video_ioctl_ops; - video->pipe.stream_state = ISS_PIPELINE_STREAM_STOPPED; - - video_set_drvdata(&video->video, video); - - return 0; -} - -void omap4iss_video_cleanup(struct iss_video *video) -{ - media_entity_cleanup(&video->video.entity); - mutex_destroy(&video->stream_lock); - mutex_destroy(&video->mutex); -} - -int omap4iss_video_register(struct iss_video *video, struct v4l2_device *vdev) -{ - int ret; - - video->video.v4l2_dev = vdev; - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - video->video.device_caps = V4L2_CAP_VIDEO_CAPTURE; - else - video->video.device_caps = V4L2_CAP_VIDEO_OUTPUT; - video->video.device_caps |= V4L2_CAP_STREAMING; - - ret = video_register_device(&video->video, VFL_TYPE_VIDEO, -1); - if (ret < 0) - dev_err(video->iss->dev, - "could not register video device (%d)\n", ret); - - return ret; -} - -void omap4iss_video_unregister(struct iss_video *video) -{ - video_unregister_device(&video->video); -} diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h deleted file mode 100644 index 19668d28b682..000000000000 --- a/drivers/staging/media/omap4iss/iss_video.h +++ /dev/null @@ -1,203 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * TI OMAP4 ISS V4L2 Driver - Generic video node - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Author: Sergio Aguirre - */ - -#ifndef OMAP4_ISS_VIDEO_H -#define OMAP4_ISS_VIDEO_H - -#include -#include -#include -#include -#include -#include - -#define ISS_VIDEO_DRIVER_NAME "issvideo" - -struct iss_device; -struct iss_video; -struct v4l2_mbus_framefmt; -struct v4l2_pix_format; - -/* - * struct iss_format_info - ISS media bus format information - * @code: V4L2 media bus format code - * @truncated: V4L2 media bus format code for the same format truncated to 10 - * bits. Identical to @code if the format is 10 bits wide or less. - * @uncompressed: V4L2 media bus format code for the corresponding uncompressed - * format. Identical to @code if the format is not DPCM compressed. - * @flavor: V4L2 media bus format code for the same pixel layout but - * shifted to be 8 bits per pixel. =0 if format is not shiftable. - * @pixelformat: V4L2 pixel format FCC identifier - * @bpp: Bits per pixel - */ -struct iss_format_info { - u32 code; - u32 truncated; - u32 uncompressed; - u32 flavor; - u32 pixelformat; - unsigned int bpp; -}; - -enum iss_pipeline_stream_state { - ISS_PIPELINE_STREAM_STOPPED = 0, - ISS_PIPELINE_STREAM_CONTINUOUS = 1, - ISS_PIPELINE_STREAM_SINGLESHOT = 2, -}; - -enum iss_pipeline_state { - /* The stream has been started on the input video node. */ - ISS_PIPELINE_STREAM_INPUT = BIT(0), - /* The stream has been started on the output video node. */ - ISS_PIPELINE_STREAM_OUTPUT = BIT(1), - /* At least one buffer is queued on the input video node. */ - ISS_PIPELINE_QUEUE_INPUT = BIT(2), - /* At least one buffer is queued on the output video node. */ - ISS_PIPELINE_QUEUE_OUTPUT = BIT(3), - /* The input entity is idle, ready to be started. */ - ISS_PIPELINE_IDLE_INPUT = BIT(4), - /* The output entity is idle, ready to be started. */ - ISS_PIPELINE_IDLE_OUTPUT = BIT(5), - /* The pipeline is currently streaming. */ - ISS_PIPELINE_STREAM = BIT(6), -}; - -/* - * struct iss_pipeline - An OMAP4 ISS hardware pipeline - * @ent_enum: Entities in the pipeline - * @error: A hardware error occurred during capture - */ -struct iss_pipeline { - struct media_pipeline pipe; - spinlock_t lock; /* Pipeline state and queue flags */ - unsigned int state; - enum iss_pipeline_stream_state stream_state; - struct iss_video *input; - struct iss_video *output; - struct media_entity_enum ent_enum; - atomic_t frame_number; - bool do_propagation; /* of frame number */ - bool error; - struct v4l2_fract max_timeperframe; - struct v4l2_subdev *external; - unsigned int external_rate; - int external_bpp; -}; - -static inline struct iss_pipeline *to_iss_pipeline(struct media_entity *entity) -{ - struct media_pipeline *pipe = media_entity_pipeline(entity); - - if (!pipe) - return NULL; - - return container_of(pipe, struct iss_pipeline, pipe); -} - -static inline int iss_pipeline_ready(struct iss_pipeline *pipe) -{ - return pipe->state == (ISS_PIPELINE_STREAM_INPUT | - ISS_PIPELINE_STREAM_OUTPUT | - ISS_PIPELINE_QUEUE_INPUT | - ISS_PIPELINE_QUEUE_OUTPUT | - ISS_PIPELINE_IDLE_INPUT | - ISS_PIPELINE_IDLE_OUTPUT); -} - -/* - * struct iss_buffer - ISS buffer - * @buffer: ISS video buffer - * @iss_addr: Physical address of the buffer. - */ -struct iss_buffer { - /* common v4l buffer stuff -- must be first */ - struct vb2_v4l2_buffer vb; - struct list_head list; - dma_addr_t iss_addr; -}; - -#define to_iss_buffer(buf) container_of(buf, struct iss_buffer, vb) - -enum iss_video_dmaqueue_flags { - /* Set if DMA queue becomes empty when ISS_PIPELINE_STREAM_CONTINUOUS */ - ISS_VIDEO_DMAQUEUE_UNDERRUN = BIT(0), - /* Set when queuing buffer to an empty DMA queue */ - ISS_VIDEO_DMAQUEUE_QUEUED = BIT(1), -}; - -#define iss_video_dmaqueue_flags_clr(video) \ - ({ (video)->dmaqueue_flags = 0; }) - -/* - * struct iss_video_operations - ISS video operations - * @queue: Resume streaming when a buffer is queued. Called on VIDIOC_QBUF - * if there was no buffer previously queued. - */ -struct iss_video_operations { - int (*queue)(struct iss_video *video, struct iss_buffer *buffer); -}; - -struct iss_video { - struct video_device video; - enum v4l2_buf_type type; - struct media_pad pad; - - struct mutex mutex; /* format and crop settings */ - atomic_t active; - - struct iss_device *iss; - - unsigned int capture_mem; - unsigned int bpl_alignment; /* alignment value */ - unsigned int bpl_zero_padding; /* whether the alignment is optional */ - unsigned int bpl_max; /* maximum bytes per line value */ - unsigned int bpl_value; /* bytes per line value */ - unsigned int bpl_padding; /* padding at end of line */ - - /* Pipeline state */ - struct iss_pipeline pipe; - struct mutex stream_lock; /* pipeline and stream states */ - bool error; - - /* Video buffers queue */ - struct vb2_queue *queue; - spinlock_t qlock; /* protects dmaqueue and error */ - struct list_head dmaqueue; - enum iss_video_dmaqueue_flags dmaqueue_flags; - - const struct iss_video_operations *ops; -}; - -#define to_iss_video(vdev) container_of(vdev, struct iss_video, video) - -struct iss_video_fh { - struct v4l2_fh vfh; - struct iss_video *video; - struct vb2_queue queue; - struct v4l2_format format; - struct v4l2_fract timeperframe; -}; - -#define to_iss_video_fh(fh) container_of(fh, struct iss_video_fh, vfh) -#define iss_video_queue_to_iss_video_fh(q) \ - container_of(q, struct iss_video_fh, queue) - -int omap4iss_video_init(struct iss_video *video, const char *name); -void omap4iss_video_cleanup(struct iss_video *video); -int omap4iss_video_register(struct iss_video *video, - struct v4l2_device *vdev); -void omap4iss_video_unregister(struct iss_video *video); -struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video); -void omap4iss_video_cancel_stream(struct iss_video *video); -struct media_pad *omap4iss_video_remote_pad(struct iss_video *video); - -const struct iss_format_info * -omap4iss_video_format_info(u32 code); - -#endif /* OMAP4_ISS_VIDEO_H */ diff --git a/include/linux/platform_data/media/omap4iss.h b/include/linux/platform_data/media/omap4iss.h deleted file mode 100644 index 2a511a8fcda7..000000000000 --- a/include/linux/platform_data/media/omap4iss.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef ARCH_ARM_PLAT_OMAP4_ISS_H -#define ARCH_ARM_PLAT_OMAP4_ISS_H - -#include - -struct iss_device; - -enum iss_interface_type { - ISS_INTERFACE_CSI2A_PHY1, - ISS_INTERFACE_CSI2B_PHY2, -}; - -/** - * struct iss_csiphy_lane: CSI2 lane position and polarity - * @pos: position of the lane - * @pol: polarity of the lane - */ -struct iss_csiphy_lane { - u8 pos; - u8 pol; -}; - -#define ISS_CSIPHY1_NUM_DATA_LANES 4 -#define ISS_CSIPHY2_NUM_DATA_LANES 1 - -/** - * struct iss_csiphy_lanes_cfg - CSI2 lane configuration - * @data: Configuration of one or two data lanes - * @clk: Clock lane configuration - */ -struct iss_csiphy_lanes_cfg { - struct iss_csiphy_lane data[ISS_CSIPHY1_NUM_DATA_LANES]; - struct iss_csiphy_lane clk; -}; - -/** - * struct iss_csi2_platform_data - CSI2 interface platform data - * @crc: Enable the cyclic redundancy check - * @vpclk_div: Video port output clock control - */ -struct iss_csi2_platform_data { - unsigned crc:1; - unsigned vpclk_div:2; - struct iss_csiphy_lanes_cfg lanecfg; -}; - -struct iss_subdev_i2c_board_info { - struct i2c_board_info *board_info; - int i2c_adapter_id; -}; - -struct iss_v4l2_subdevs_group { - struct iss_subdev_i2c_board_info *subdevs; - enum iss_interface_type interface; - union { - struct iss_csi2_platform_data csi2; - } bus; /* gcc < 4.6.0 chokes on anonymous union initializers */ -}; - -struct iss_platform_data { - struct iss_v4l2_subdevs_group *subdevs; - void (*set_constraints)(struct iss_device *iss, bool enable); -}; - -#endif -- cgit v1.2.3 From 483c5c2bc6b1c0d17214e2672032def605ff2ba9 Mon Sep 17 00:00:00 2001 From: Yanteng Si Date: Fri, 20 Sep 2024 13:34:23 +0800 Subject: serial: clean up uart_info Since commit ebd2c8f6d2ec ("serial: kill off uart_info") has removed uart_info, the uart_info declaration looks lonely, let it go. Signed-off-by: Yanteng Si Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240920053423.1373354-1-siyanteng@cqsoftware.com.cn Signed-off-by: Greg Kroah-Hartman --- include/linux/platform_data/sa11x0-serial.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/sa11x0-serial.h b/include/linux/platform_data/sa11x0-serial.h index 8b79ab08af45..a88096bc74e4 100644 --- a/include/linux/platform_data/sa11x0-serial.h +++ b/include/linux/platform_data/sa11x0-serial.h @@ -10,7 +10,6 @@ #define SA11X0_SERIAL_H struct uart_port; -struct uart_info; /* * This is a temporary structure for registering these -- cgit v1.2.3 From 2b627246c0cf2b54f1b17531dde964cf5b99b2a5 Mon Sep 17 00:00:00 2001 From: Pavan Holla Date: Tue, 10 Sep 2024 10:15:21 +0000 Subject: platform/chrome: Update EC feature flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define EC_FEATURE_UCSI_PPM to enable usage of the cros_ec_ucsi driver. Also, add any feature flags that are implemented by the EC but are missing in the kernel header. Signed-off-by: Pavan Holla Signed-off-by: Łukasz Bartosik Acked-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20240910101527.603452-3-ukaszb@chromium.org Signed-off-by: Lee Jones --- include/linux/platform_data/cros_ec_commands.h | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index e574b790be6f..b3c4993e656e 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -1312,6 +1312,38 @@ enum ec_feature_code { * The EC supports the AP composing VDMs for us to send. */ EC_FEATURE_TYPEC_AP_VDM_SEND = 46, + /* + * The EC supports system safe mode panic recovery. + */ + EC_FEATURE_SYSTEM_SAFE_MODE = 47, + /* + * The EC will reboot on runtime assertion failures. + */ + EC_FEATURE_ASSERT_REBOOTS = 48, + /* + * The EC image is built with tokenized logging enabled. + */ + EC_FEATURE_TOKENIZED_LOGGING = 49, + /* + * The EC supports triggering an STB dump. + */ + EC_FEATURE_AMD_STB_DUMP = 50, + /* + * The EC supports memory dump commands. + */ + EC_FEATURE_MEMORY_DUMP = 51, + /* + * The EC supports DP2.1 capability + */ + EC_FEATURE_TYPEC_DP2_1 = 52, + /* + * The MCU is System Companion Processor Core 1 + */ + EC_FEATURE_SCP_C1 = 53, + /* + * The EC supports UCSI PPM. + */ + EC_FEATURE_UCSI_PPM = 54, }; #define EC_FEATURE_MASK_0(event_code) BIT(event_code % 32) -- cgit v1.2.3 From 7506ebcd662b868780774d191a7c024c18c557a8 Mon Sep 17 00:00:00 2001 From: Naresh Solanki Date: Mon, 7 Oct 2024 14:34:24 +0530 Subject: hwmon: (max6639) : Configure based on DT property Remove platform data & initialize with defaults configuration & overwrite based on DT properties. Signed-off-by: Naresh Solanki Message-ID: <20241007090426.811736-1-naresh.solanki@9elements.com> [groeck: Dropped some unnecessary empty lines] Signed-off-by: Guenter Roeck --- drivers/hwmon/max6639.c | 83 +++++++++++++++++++++++++---------- include/linux/platform_data/max6639.h | 15 ------- 2 files changed, 60 insertions(+), 38 deletions(-) delete mode 100644 include/linux/platform_data/max6639.h (limited to 'include/linux/platform_data') diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c index c955b0f3a8d3..32b4d54b2076 100644 --- a/drivers/hwmon/max6639.c +++ b/drivers/hwmon/max6639.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -531,14 +530,49 @@ static int rpm_range_to_reg(int range) return 1; /* default: 4000 RPM */ } +static int max6639_probe_child_from_dt(struct i2c_client *client, + struct device_node *child, + struct max6639_data *data) + +{ + struct device *dev = &client->dev; + u32 i; + int err, val; + + err = of_property_read_u32(child, "reg", &i); + if (err) { + dev_err(dev, "missing reg property of %pOFn\n", child); + return err; + } + + if (i > 1) { + dev_err(dev, "Invalid fan index reg %d\n", i); + return -EINVAL; + } + + err = of_property_read_u32(child, "pulses-per-revolution", &val); + if (!err) { + if (val < 1 || val > 5) { + dev_err(dev, "invalid pulses-per-revolution %d of %pOFn\n", val, child); + return -EINVAL; + } + data->ppr[i] = val; + } + + err = of_property_read_u32(child, "max-rpm", &val); + if (!err) + data->rpm_range[i] = rpm_range_to_reg(val); + + return 0; +} + static int max6639_init_client(struct i2c_client *client, struct max6639_data *data) { - struct max6639_platform_data *max6639_info = - dev_get_platdata(&client->dev); - int i; - int rpm_range = 1; /* default: 4000 RPM */ - int err, ppr; + struct device *dev = &client->dev; + const struct device_node *np = dev->of_node; + struct device_node *child; + int i, err; /* Reset chip to default values, see below for GCONFIG setup */ err = regmap_write(data->regmap, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_POR); @@ -546,21 +580,29 @@ static int max6639_init_client(struct i2c_client *client, return err; /* Fans pulse per revolution is 2 by default */ - if (max6639_info && max6639_info->ppr > 0 && - max6639_info->ppr < 5) - ppr = max6639_info->ppr; - else - ppr = 2; + data->ppr[0] = 2; + data->ppr[1] = 2; + + /* default: 4000 RPM */ + data->rpm_range[0] = 1; + data->rpm_range[1] = 1; - data->ppr[0] = ppr; - data->ppr[1] = ppr; + for_each_child_of_node(np, child) { + if (strcmp(child->name, "fan")) + continue; - if (max6639_info) - rpm_range = rpm_range_to_reg(max6639_info->rpm_range); - data->rpm_range[0] = rpm_range; - data->rpm_range[1] = rpm_range; + err = max6639_probe_child_from_dt(client, child, data); + if (err) { + of_node_put(child); + return err; + } + } for (i = 0; i < MAX6639_NUM_CHANNELS; i++) { + err = regmap_set_bits(data->regmap, MAX6639_REG_OUTPUT_MASK, BIT(1 - i)); + if (err) + return err; + /* Set Fan pulse per revolution */ err = max6639_set_ppr(data, i, data->ppr[i]); if (err) @@ -573,12 +615,7 @@ static int max6639_init_client(struct i2c_client *client, return err; /* Fans PWM polarity high by default */ - if (max6639_info) { - if (max6639_info->pwm_polarity == 0) - err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x00); - else - err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x02); - } + err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x00); if (err) return err; diff --git a/include/linux/platform_data/max6639.h b/include/linux/platform_data/max6639.h deleted file mode 100644 index 65bfdb4fdc15..000000000000 --- a/include/linux/platform_data/max6639.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _LINUX_MAX6639_H -#define _LINUX_MAX6639_H - -#include - -/* platform data for the MAX6639 temperature sensor and fan control */ - -struct max6639_platform_data { - bool pwm_polarity; /* Polarity low (0) or high (1, default) */ - int ppr; /* Pulses per rotation 1..4 (default == 2) */ - int rpm_range; /* 2000, 4000 (default), 8000 or 16000 */ -}; - -#endif /* _LINUX_MAX6639_H */ -- cgit v1.2.3 From 16220cb315a0a10d2a003d9af534988686e675ea Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Fri, 8 Nov 2024 17:57:05 -0800 Subject: net: dsa: microchip: Add LAN9646 switch support to KSZ DSA driver LAN9646 switch is a 6-port switch with functions like KSZ9897. It has 4 internal PHYs and 1 SGMII port. The chip id read from hardware is same as KSZ9477, so software driver needs to create a new chip id and group allowable functions under its chip data structure to differentiate the product. Signed-off-by: Tristram Ha Link: https://patch.msgid.link/20241109015705.82685-3-Tristram.Ha@microchip.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/microchip/ksz9477.c | 4 +++ drivers/net/dsa/microchip/ksz9477_i2c.c | 14 +++++++- drivers/net/dsa/microchip/ksz_common.c | 50 +++++++++++++++++++++++++++-- drivers/net/dsa/microchip/ksz_common.h | 1 + drivers/net/dsa/microchip/ksz_spi.c | 7 ++++ include/linux/platform_data/microchip-ksz.h | 1 + 6 files changed, 74 insertions(+), 3 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 0ba658a72d8f..d16817e0476f 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -1131,6 +1131,10 @@ void ksz9477_config_cpu_port(struct dsa_switch *ds) if (i == dev->cpu_port) continue; ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED); + + /* Power down the internal PHY if port is unused. */ + if (dsa_is_unused_port(ds, i) && dev->info->internal_phy[i]) + ksz_pwrite16(dev, i, 0x100, BMCR_PDOWN); } } diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c index 7d7560f23a73..1c6d7fc16772 100644 --- a/drivers/net/dsa/microchip/ksz9477_i2c.c +++ b/drivers/net/dsa/microchip/ksz9477_i2c.c @@ -2,7 +2,7 @@ /* * Microchip KSZ9477 series register access through I2C * - * Copyright (C) 2018-2019 Microchip Technology Inc. + * Copyright (C) 2018-2024 Microchip Technology Inc. */ #include @@ -16,6 +16,8 @@ KSZ_REGMAP_TABLE(ksz9477, not_used, 16, 0, 0); static int ksz9477_i2c_probe(struct i2c_client *i2c) { + const struct ksz_chip_data *chip; + struct device *ddev = &i2c->dev; struct regmap_config rc; struct ksz_device *dev; int i, ret; @@ -24,6 +26,12 @@ static int ksz9477_i2c_probe(struct i2c_client *i2c) if (!dev) return -ENOMEM; + chip = device_get_match_data(ddev); + if (!chip) + return -EINVAL; + + /* Save chip id to do special initialization when probing. */ + dev->chip_id = chip->chip_id; for (i = 0; i < __KSZ_NUM_REGMAPS; i++) { rc = ksz9477_regmap_config[i]; rc.lock_arg = &dev->regmap_mutex; @@ -111,6 +119,10 @@ static const struct of_device_id ksz9477_dt_ids[] = { .compatible = "microchip,ksz9567", .data = &ksz_switch_chips[KSZ9567] }, + { + .compatible = "microchip,lan9646", + .data = &ksz_switch_chips[LAN9646] + }, {}, }; MODULE_DEVICE_TABLE(of, ksz9477_dt_ids); diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index d57782cdda59..920443ee8ffd 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -1908,6 +1908,41 @@ const struct ksz_chip_data ksz_switch_chips[] = { .internal_phy = {true, true, true, true, false, false, true, true}, }, + + [LAN9646] = { + .chip_id = LAN9646_CHIP_ID, + .dev_name = "LAN9646", + .num_vlans = 4096, + .num_alus = 4096, + .num_statics = 16, + .cpu_ports = 0x7F, /* can be configured as cpu port */ + .port_cnt = 7, /* total physical port count */ + .port_nirqs = 4, + .num_tx_queues = 4, + .num_ipms = 8, + .ops = &ksz9477_dev_ops, + .phylink_mac_ops = &ksz9477_phylink_mac_ops, + .phy_errata_9477 = true, + .mib_names = ksz9477_mib_names, + .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), + .reg_mib_cnt = MIB_COUNTER_NUM, + .regs = ksz9477_regs, + .masks = ksz9477_masks, + .shifts = ksz9477_shifts, + .xmii_ctrl0 = ksz9477_xmii_ctrl0, + .xmii_ctrl1 = ksz9477_xmii_ctrl1, + .supports_mii = {false, false, false, false, + false, true, true}, + .supports_rmii = {false, false, false, false, + false, true, true}, + .supports_rgmii = {false, false, false, false, + false, true, true}, + .internal_phy = {true, true, true, true, + true, false, false}, + .gbit_capable = {true, true, true, true, true, true, true}, + .wr_table = &ksz9477_register_set, + .rd_table = &ksz9477_register_set, + }, }; EXPORT_SYMBOL_GPL(ksz_switch_chips); @@ -2970,6 +3005,7 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) case KSZ9896_CHIP_ID: /* KSZ9896C Errata DS80000757A Module 3 */ case KSZ9897_CHIP_ID: + case LAN9646_CHIP_ID: /* KSZ9897R Errata DS80000758C Module 4 */ /* Energy Efficient Ethernet (EEE) feature select must be manually disabled * The EEE feature is enabled by default, but it is not fully @@ -3230,6 +3266,7 @@ static void ksz_port_teardown(struct dsa_switch *ds, int port) case KSZ9893_CHIP_ID: case KSZ9896_CHIP_ID: case KSZ9897_CHIP_ID: + case LAN9646_CHIP_ID: if (dsa_is_user_port(ds, port)) ksz9477_port_acl_free(dev, port); } @@ -3286,7 +3323,8 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds, dev->chip_id == KSZ9477_CHIP_ID || dev->chip_id == KSZ9896_CHIP_ID || dev->chip_id == KSZ9897_CHIP_ID || - dev->chip_id == KSZ9567_CHIP_ID) + dev->chip_id == KSZ9567_CHIP_ID || + dev->chip_id == LAN9646_CHIP_ID) proto = DSA_TAG_PROTO_KSZ9477; if (is_lan937x(dev)) @@ -3405,6 +3443,7 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port) case LAN9372_CHIP_ID: case LAN9373_CHIP_ID: case LAN9374_CHIP_ID: + case LAN9646_CHIP_ID: return KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; } @@ -3427,6 +3466,7 @@ static int ksz_validate_eee(struct dsa_switch *ds, int port) case KSZ9893_CHIP_ID: case KSZ9896_CHIP_ID: case KSZ9897_CHIP_ID: + case LAN9646_CHIP_ID: return 0; } @@ -3779,7 +3819,10 @@ static int ksz_switch_detect(struct ksz_device *dev) case LAN9372_CHIP_ID: case LAN9373_CHIP_ID: case LAN9374_CHIP_ID: - dev->chip_id = id32; + + /* LAN9646 does not have its own chip id. */ + if (dev->chip_id != LAN9646_CHIP_ID) + dev->chip_id = id32; break; case KSZ9893_CHIP_ID: ret = ksz_read8(dev, REG_CHIP_ID4, @@ -3818,6 +3861,7 @@ static int ksz_cls_flower_add(struct dsa_switch *ds, int port, case KSZ9893_CHIP_ID: case KSZ9896_CHIP_ID: case KSZ9897_CHIP_ID: + case LAN9646_CHIP_ID: return ksz9477_cls_flower_add(ds, port, cls, ingress); } @@ -3838,6 +3882,7 @@ static int ksz_cls_flower_del(struct dsa_switch *ds, int port, case KSZ9893_CHIP_ID: case KSZ9896_CHIP_ID: case KSZ9897_CHIP_ID: + case LAN9646_CHIP_ID: return ksz9477_cls_flower_del(ds, port, cls, ingress); } @@ -4925,6 +4970,7 @@ static int ksz_parse_drive_strength(struct ksz_device *dev) case KSZ9893_CHIP_ID: case KSZ9896_CHIP_ID: case KSZ9897_CHIP_ID: + case LAN9646_CHIP_ID: return ksz9477_drive_strength_write(dev, of_props, ARRAY_SIZE(of_props)); default: diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index bbb548af201e..b3bb75ca0796 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -236,6 +236,7 @@ enum ksz_model { LAN9372, LAN9373, LAN9374, + LAN9646, }; enum ksz_regs { diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c index 1c6652f2b9fe..108a958dc356 100644 --- a/drivers/net/dsa/microchip/ksz_spi.c +++ b/drivers/net/dsa/microchip/ksz_spi.c @@ -54,6 +54,8 @@ static int ksz_spi_probe(struct spi_device *spi) if (!chip) return -EINVAL; + /* Save chip id to do special initialization when probing. */ + dev->chip_id = chip->chip_id; if (chip->chip_id == KSZ88X3_CHIP_ID) regmap_config = ksz8863_regmap_config; else if (chip->chip_id == KSZ8795_CHIP_ID || @@ -203,6 +205,10 @@ static const struct of_device_id ksz_dt_ids[] = { .compatible = "microchip,lan9374", .data = &ksz_switch_chips[LAN9374] }, + { + .compatible = "microchip,lan9646", + .data = &ksz_switch_chips[LAN9646] + }, {}, }; MODULE_DEVICE_TABLE(of, ksz_dt_ids); @@ -228,6 +234,7 @@ static const struct spi_device_id ksz_spi_ids[] = { { "lan9372" }, { "lan9373" }, { "lan9374" }, + { "lan9646" }, { }, }; MODULE_DEVICE_TABLE(spi, ksz_spi_ids); diff --git a/include/linux/platform_data/microchip-ksz.h b/include/linux/platform_data/microchip-ksz.h index 2ee1a679e592..0e0e8fe6975f 100644 --- a/include/linux/platform_data/microchip-ksz.h +++ b/include/linux/platform_data/microchip-ksz.h @@ -42,6 +42,7 @@ enum ksz_chip_id { LAN9372_CHIP_ID = 0x00937200, LAN9373_CHIP_ID = 0x00937300, LAN9374_CHIP_ID = 0x00937400, + LAN9646_CHIP_ID = 0x00964600, }; struct ksz_platform_data { -- cgit v1.2.3 From dcbef0798eb825cd584f7a93f62bed63f7fbbfc9 Mon Sep 17 00:00:00 2001 From: Lizhi Hou Date: Wed, 18 Sep 2024 11:10:22 -0700 Subject: dmaengine: amd: qdma: Remove using the private get and set dma_ops APIs The get_dma_ops and set_dma_ops APIs were never for driver to use. Remove these calls from QDMA driver. Instead, pass the DMA device pointer from the qdma_platdata structure. Fixes: 73d5fc92a11c ("dmaengine: amd: qdma: Add AMD QDMA driver") Signed-off-by: Lizhi Hou Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/20240918181022.2155715-1-lizhi.hou@amd.com Signed-off-by: Vinod Koul --- drivers/dma/amd/qdma/qdma.c | 28 ++++++++++++---------------- include/linux/platform_data/amd_qdma.h | 2 ++ 2 files changed, 14 insertions(+), 16 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/dma/amd/qdma/qdma.c b/drivers/dma/amd/qdma/qdma.c index 6d9079458fe9..66f00ad67351 100644 --- a/drivers/dma/amd/qdma/qdma.c +++ b/drivers/dma/amd/qdma/qdma.c @@ -7,9 +7,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -492,18 +492,9 @@ static int qdma_device_verify(struct qdma_device *qdev) static int qdma_device_setup(struct qdma_device *qdev) { - struct device *dev = &qdev->pdev->dev; u32 ring_sz = QDMA_DEFAULT_RING_SIZE; int ret = 0; - while (dev && get_dma_ops(dev)) - dev = dev->parent; - if (!dev) { - qdma_err(qdev, "dma device not found"); - return -EINVAL; - } - set_dma_ops(&qdev->pdev->dev, get_dma_ops(dev)); - ret = qdma_setup_fmap_context(qdev); if (ret) { qdma_err(qdev, "Failed setup fmap context"); @@ -548,11 +539,12 @@ static void qdma_free_queue_resources(struct dma_chan *chan) { struct qdma_queue *queue = to_qdma_queue(chan); struct qdma_device *qdev = queue->qdev; - struct device *dev = qdev->dma_dev.dev; + struct qdma_platdata *pdata; qdma_clear_queue_context(queue); vchan_free_chan_resources(&queue->vchan); - dma_free_coherent(dev, queue->ring_size * QDMA_MM_DESC_SIZE, + pdata = dev_get_platdata(&qdev->pdev->dev); + dma_free_coherent(pdata->dma_dev, queue->ring_size * QDMA_MM_DESC_SIZE, queue->desc_base, queue->dma_desc_base); } @@ -565,6 +557,7 @@ static int qdma_alloc_queue_resources(struct dma_chan *chan) struct qdma_queue *queue = to_qdma_queue(chan); struct qdma_device *qdev = queue->qdev; struct qdma_ctxt_sw_desc desc; + struct qdma_platdata *pdata; size_t size; int ret; @@ -572,8 +565,9 @@ static int qdma_alloc_queue_resources(struct dma_chan *chan) if (ret) return ret; + pdata = dev_get_platdata(&qdev->pdev->dev); size = queue->ring_size * QDMA_MM_DESC_SIZE; - queue->desc_base = dma_alloc_coherent(qdev->dma_dev.dev, size, + queue->desc_base = dma_alloc_coherent(pdata->dma_dev, size, &queue->dma_desc_base, GFP_KERNEL); if (!queue->desc_base) { @@ -588,7 +582,7 @@ static int qdma_alloc_queue_resources(struct dma_chan *chan) if (ret) { qdma_err(qdev, "Failed to setup SW desc ctxt for %s", chan->name); - dma_free_coherent(qdev->dma_dev.dev, size, queue->desc_base, + dma_free_coherent(pdata->dma_dev, size, queue->desc_base, queue->dma_desc_base); return ret; } @@ -948,8 +942,9 @@ static int qdma_init_error_irq(struct qdma_device *qdev) static int qdmam_alloc_qintr_rings(struct qdma_device *qdev) { - u32 ctxt[QDMA_CTXT_REGMAP_LEN]; + struct qdma_platdata *pdata = dev_get_platdata(&qdev->pdev->dev); struct device *dev = &qdev->pdev->dev; + u32 ctxt[QDMA_CTXT_REGMAP_LEN]; struct qdma_intr_ring *ring; struct qdma_ctxt_intr intr_ctxt; u32 vector; @@ -969,7 +964,8 @@ static int qdmam_alloc_qintr_rings(struct qdma_device *qdev) ring->msix_id = qdev->err_irq_idx + i + 1; ring->ridx = i; ring->color = 1; - ring->base = dmam_alloc_coherent(dev, QDMA_INTR_RING_SIZE, + ring->base = dmam_alloc_coherent(pdata->dma_dev, + QDMA_INTR_RING_SIZE, &ring->dev_base, GFP_KERNEL); if (!ring->base) { qdma_err(qdev, "Failed to alloc intr ring %d", i); diff --git a/include/linux/platform_data/amd_qdma.h b/include/linux/platform_data/amd_qdma.h index 576d952f97ed..967a6ef31cf9 100644 --- a/include/linux/platform_data/amd_qdma.h +++ b/include/linux/platform_data/amd_qdma.h @@ -26,11 +26,13 @@ struct dma_slave_map; * @max_mm_channels: Maximum number of MM DMA channels in each direction * @device_map: DMA slave map * @irq_index: The index of first IRQ + * @dma_dev: The device pointer for dma operations */ struct qdma_platdata { u32 max_mm_channels; u32 irq_index; struct dma_slave_map *device_map; + struct device *dma_dev; }; #endif /* _PLATDATA_AMD_QDMA_H */ -- cgit v1.2.3 From 828fd3f1d611cff5accb9fbff75f6bb011d8c9e2 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 16 Dec 2024 09:32:17 +0100 Subject: Input: davinci-keyscan - remove leftover header The corresponding driver was removed two years ago but the platform data header was left behind. Remove it now. Fixes: 3c9cb34939fb ("input: remove davinci keyboard driver") Signed-off-by: Bartosz Golaszewski Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/20241216083218.22926-1-brgl@bgdev.pl Signed-off-by: Dmitry Torokhov --- include/linux/platform_data/keyscan-davinci.h | 29 --------------------------- 1 file changed, 29 deletions(-) delete mode 100644 include/linux/platform_data/keyscan-davinci.h (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/keyscan-davinci.h b/include/linux/platform_data/keyscan-davinci.h deleted file mode 100644 index 260d596ba0af..000000000000 --- a/include/linux/platform_data/keyscan-davinci.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2009 Texas Instruments, Inc - * - * Author: Miguel Aguilar - */ - -#ifndef DAVINCI_KEYSCAN_H -#define DAVINCI_KEYSCAN_H - -#include - -enum davinci_matrix_types { - DAVINCI_KEYSCAN_MATRIX_4X4, - DAVINCI_KEYSCAN_MATRIX_5X3, -}; - -struct davinci_ks_platform_data { - int (*device_enable)(struct device *dev); - unsigned short *keymap; - u32 keymapsize; - u8 rep:1; - u8 strobe; - u8 interval; - u8 matrix_type; -}; - -#endif - -- cgit v1.2.3 From 7c4b497fd4032935676b9024396f187fee005739 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 17 Dec 2024 18:41:54 +0100 Subject: clk: davinci: remove platform data struct There are no board files using struct davinci_pll_platform_data anymore. The structure itself is currently used to store a single pointer. Let's remove the struct definition, the header and rework the driver to not require the syscon regmap to be stored in probe(). Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20241217174154.84441-1-brgl@bgdev.pl Reviewed-by: David Lechner Signed-off-by: Stephen Boyd --- drivers/clk/davinci/pll.c | 32 +++------------------------ include/linux/platform_data/clk-davinci-pll.h | 21 ------------------ 2 files changed, 3 insertions(+), 50 deletions(-) delete mode 100644 include/linux/platform_data/clk-davinci-pll.h (limited to 'include/linux/platform_data') diff --git a/drivers/clk/davinci/pll.c b/drivers/clk/davinci/pll.c index 5bbbb3a66477..82727b1fc67a 100644 --- a/drivers/clk/davinci/pll.c +++ b/drivers/clk/davinci/pll.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -840,27 +839,6 @@ int of_davinci_pll_init(struct device *dev, struct device_node *node, return 0; } -static struct davinci_pll_platform_data *davinci_pll_get_pdata(struct device *dev) -{ - struct davinci_pll_platform_data *pdata = dev_get_platdata(dev); - - /* - * Platform data is optional, so allocate a new struct if one was not - * provided. For device tree, this will always be the case. - */ - if (!pdata) - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - /* for device tree, we need to fill in the struct */ - if (dev->of_node) - pdata->cfgchip = - syscon_regmap_lookup_by_compatible("ti,da830-cfgchip"); - - return pdata; -} - /* needed in early boot for clocksource/clockevent */ #ifdef CONFIG_ARCH_DAVINCI_DA850 CLK_OF_DECLARE(da850_pll0, "ti,da850-pll0", of_da850_pll0_init); @@ -890,8 +868,8 @@ typedef int (*davinci_pll_init)(struct device *dev, void __iomem *base, static int davinci_pll_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct davinci_pll_platform_data *pdata; davinci_pll_init pll_init = NULL; + struct regmap *cfgchip; void __iomem *base; pll_init = device_get_match_data(dev); @@ -903,17 +881,13 @@ static int davinci_pll_probe(struct platform_device *pdev) return -EINVAL; } - pdata = davinci_pll_get_pdata(dev); - if (!pdata) { - dev_err(dev, "missing platform data\n"); - return -EINVAL; - } + cfgchip = syscon_regmap_lookup_by_compatible("ti,da830-cfgchip"); base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); - return pll_init(dev, base, pdata->cfgchip); + return pll_init(dev, base, cfgchip); } static struct platform_driver davinci_pll_driver = { diff --git a/include/linux/platform_data/clk-davinci-pll.h b/include/linux/platform_data/clk-davinci-pll.h deleted file mode 100644 index e55dab1d578b..000000000000 --- a/include/linux/platform_data/clk-davinci-pll.h +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * PLL clock driver for TI Davinci SoCs - * - * Copyright (C) 2018 David Lechner - */ - -#ifndef __LINUX_PLATFORM_DATA_CLK_DAVINCI_PLL_H__ -#define __LINUX_PLATFORM_DATA_CLK_DAVINCI_PLL_H__ - -#include - -/** - * davinci_pll_platform_data - * @cfgchip: CFGCHIP syscon regmap - */ -struct davinci_pll_platform_data { - struct regmap *cfgchip; -}; - -#endif /* __LINUX_PLATFORM_DATA_CLK_DAVINCI_PLL_H__ */ -- cgit v1.2.3 From 5ffa0dbfdc9fc05acae02d5b0dc766ec778569ac Mon Sep 17 00:00:00 2001 From: Dawid Niedzwiecki Date: Fri, 6 Dec 2024 09:15:13 +0000 Subject: platform/chrome: cros_ec: jump to RW before probing There are EC devices, like FPMCU, that use RWSIG as a method of authenticating RW section. After the authentication succeeds, EC device waits some time before jumping to RW. EC can be probed before the jump, which means there is a time window after jump to RW in which EC won't respond, because it is not initialized. It can cause a communication errors after probing. To avoid such problems, send the RWSIG continue command first, which skips waiting for the jump to RW. Send the command more times, to make sure EC is ready in RW before the start of the actual probing process. If a EC device doesn't support the RWSIG, it will respond with invalid command error code and probing will continue as usual. Signed-off-by: Dawid Niedzwiecki Link: https://lore.kernel.org/r/20241206091514.2538350-2-dawidn@google.com Signed-off-by: Tzung-Bi Shih --- drivers/platform/chrome/cros_ec.c | 5 +++ drivers/platform/chrome/cros_ec_i2c.c | 3 +- drivers/platform/chrome/cros_ec_ishtp.c | 2 +- drivers/platform/chrome/cros_ec_lpc.c | 2 +- drivers/platform/chrome/cros_ec_proto.c | 60 +++++++++++++++++++++++++++++ drivers/platform/chrome/cros_ec_rpmsg.c | 2 +- drivers/platform/chrome/cros_ec_spi.c | 2 +- drivers/platform/chrome/cros_ec_uart.c | 2 +- include/linux/platform_data/cros_ec_proto.h | 2 + 9 files changed, 74 insertions(+), 6 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index e821b3d39590..110771a8645e 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -204,6 +204,11 @@ int cros_ec_register(struct cros_ec_device *ec_dev) mutex_init(&ec_dev->lock); lockdep_set_class(&ec_dev->lock, &ec_dev->lockdep_key); + /* Send RWSIG continue to jump to RW for devices using RWSIG. */ + err = cros_ec_rwsig_continue(ec_dev); + if (err) + dev_info(dev, "Failed to continue RWSIG: %d\n", err); + err = cros_ec_query_all(ec_dev); if (err) { dev_err(dev, "Cannot identify the EC: error %d\n", err); diff --git a/drivers/platform/chrome/cros_ec_i2c.c b/drivers/platform/chrome/cros_ec_i2c.c index 62662ba5bf6e..38af97cdaab2 100644 --- a/drivers/platform/chrome/cros_ec_i2c.c +++ b/drivers/platform/chrome/cros_ec_i2c.c @@ -305,7 +305,8 @@ static int cros_ec_i2c_probe(struct i2c_client *client) ec_dev->phys_name = client->adapter->name; ec_dev->din_size = sizeof(struct ec_host_response_i2c) + sizeof(struct ec_response_get_protocol_info); - ec_dev->dout_size = sizeof(struct ec_host_request_i2c); + ec_dev->dout_size = sizeof(struct ec_host_request_i2c) + + sizeof(struct ec_params_rwsig_action); err = cros_ec_register(ec_dev); if (err) { diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c index 5ac37bd024c8..7e7190b30cbb 100644 --- a/drivers/platform/chrome/cros_ec_ishtp.c +++ b/drivers/platform/chrome/cros_ec_ishtp.c @@ -557,7 +557,7 @@ static int cros_ec_dev_init(struct ishtp_cl_data *client_data) ec_dev->phys_name = dev_name(dev); ec_dev->din_size = sizeof(struct cros_ish_in_msg) + sizeof(struct ec_response_get_protocol_info); - ec_dev->dout_size = sizeof(struct cros_ish_out_msg); + ec_dev->dout_size = sizeof(struct cros_ish_out_msg) + sizeof(struct ec_params_rwsig_action); return cros_ec_register(ec_dev); } diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 8470b7f2b135..17c2578bbc58 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -573,7 +573,7 @@ static int cros_ec_lpc_probe(struct platform_device *pdev) ec_dev->cmd_readmem = cros_ec_lpc_readmem; ec_dev->din_size = sizeof(struct ec_host_response) + sizeof(struct ec_response_get_protocol_info); - ec_dev->dout_size = sizeof(struct ec_host_request); + ec_dev->dout_size = sizeof(struct ec_host_request) + sizeof(struct ec_params_rwsig_action); ec_dev->priv = ec_lpc; /* diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 5c9a53dffcf9..ed3623b54bc3 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -15,6 +15,8 @@ #include "cros_ec_trace.h" #define EC_COMMAND_RETRIES 50 +#define RWSIG_CONTINUE_RETRIES 8 +#define RWSIG_CONTINUE_MAX_ERRORS_IN_ROW 3 static const int cros_ec_error_map[] = { [EC_RES_INVALID_COMMAND] = -EOPNOTSUPP, @@ -288,6 +290,64 @@ exit: return ret; } +int cros_ec_rwsig_continue(struct cros_ec_device *ec_dev) +{ + struct cros_ec_command *msg; + struct ec_params_rwsig_action *rwsig_action; + int ret = 0; + int error_count = 0; + + ec_dev->proto_version = 3; + + msg = kmalloc(sizeof(*msg) + sizeof(*rwsig_action), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + msg->version = 0; + msg->command = EC_CMD_RWSIG_ACTION; + msg->insize = 0; + msg->outsize = sizeof(*rwsig_action); + + rwsig_action = (struct ec_params_rwsig_action *)msg->data; + rwsig_action->action = RWSIG_ACTION_CONTINUE; + + for (int i = 0; i < RWSIG_CONTINUE_RETRIES; i++) { + ret = cros_ec_send_command(ec_dev, msg); + + if (ret < 0) { + if (++error_count >= RWSIG_CONTINUE_MAX_ERRORS_IN_ROW) + break; + } else if (msg->result == EC_RES_INVALID_COMMAND) { + /* + * If EC_RES_INVALID_COMMAND is retured, it means RWSIG + * is not supported or EC is already in RW, so there is + * nothing left to do. + */ + break; + } else if (msg->result != EC_RES_SUCCESS) { + /* Unexpected command error. */ + ret = cros_ec_map_error(msg->result); + break; + } else { + /* + * The EC_CMD_RWSIG_ACTION succeed. Send the command + * more times, to make sure EC is in RW. A following + * command can timeout, because EC may need some time to + * initialize after jump to RW. + */ + error_count = 0; + } + + if (ret != -ETIMEDOUT) + usleep_range(90000, 100000); + } + + kfree(msg); + + return ret; +} +EXPORT_SYMBOL(cros_ec_rwsig_continue); + static int cros_ec_get_proto_info(struct cros_ec_device *ec_dev, int devidx) { struct cros_ec_command *msg; diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c b/drivers/platform/chrome/cros_ec_rpmsg.c index 39d3b50a7c09..bc2666491db1 100644 --- a/drivers/platform/chrome/cros_ec_rpmsg.c +++ b/drivers/platform/chrome/cros_ec_rpmsg.c @@ -231,7 +231,7 @@ static int cros_ec_rpmsg_probe(struct rpmsg_device *rpdev) ec_dev->phys_name = dev_name(&rpdev->dev); ec_dev->din_size = sizeof(struct ec_host_response) + sizeof(struct ec_response_get_protocol_info); - ec_dev->dout_size = sizeof(struct ec_host_request); + ec_dev->dout_size = sizeof(struct ec_host_request) + sizeof(struct ec_params_rwsig_action); dev_set_drvdata(dev, ec_dev); ec_rpmsg->rpdev = rpdev; diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index 86a3d32a7763..946373238502 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -766,7 +766,7 @@ static int cros_ec_spi_probe(struct spi_device *spi) ec_dev->din_size = EC_MSG_PREAMBLE_COUNT + sizeof(struct ec_host_response) + sizeof(struct ec_response_get_protocol_info); - ec_dev->dout_size = sizeof(struct ec_host_request); + ec_dev->dout_size = sizeof(struct ec_host_request) + sizeof(struct ec_params_rwsig_action); ec_spi->last_transfer_ns = ktime_get_ns(); diff --git a/drivers/platform/chrome/cros_ec_uart.c b/drivers/platform/chrome/cros_ec_uart.c index 62bc24f6dcc7..19c179d49c90 100644 --- a/drivers/platform/chrome/cros_ec_uart.c +++ b/drivers/platform/chrome/cros_ec_uart.c @@ -283,7 +283,7 @@ static int cros_ec_uart_probe(struct serdev_device *serdev) ec_dev->pkt_xfer = cros_ec_uart_pkt_xfer; ec_dev->din_size = sizeof(struct ec_host_response) + sizeof(struct ec_response_get_protocol_info); - ec_dev->dout_size = sizeof(struct ec_host_request); + ec_dev->dout_size = sizeof(struct ec_host_request) + sizeof(struct ec_params_rwsig_action); serdev_device_set_client_ops(serdev, &cros_ec_uart_client_ops); diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index b34ed0cc1f8d..701389c16fa7 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -246,6 +246,8 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, struct cros_ec_command *msg); +int cros_ec_rwsig_continue(struct cros_ec_device *ec_dev); + int cros_ec_query_all(struct cros_ec_device *ec_dev); int cros_ec_get_next_event(struct cros_ec_device *ec_dev, -- cgit v1.2.3 From fb1e493426d4da77a1d192fffa4dc55fc4ad5741 Mon Sep 17 00:00:00 2001 From: Rob Barnes Date: Wed, 18 Dec 2024 01:57:59 +0000 Subject: platform/chrome: cros_ec_lpc: Only check for events on MKBP notifies Only check EC for MKBP events when the ACPI notify value indicates the notify is due to an MKBP host event. This reduces unnecessary queries to the EC. Notify value 0x80 is reserved for devices specific notifies. It is used by many devices to indicate various events. It's only used by cros_ec for MKBP events. Signed-off-by: Rob Barnes Link: https://lore.kernel.org/r/20241218015759.3558830-1-robbarnes@google.com Signed-off-by: Tzung-Bi Shih --- drivers/platform/chrome/cros_ec_lpc.c | 2 +- include/linux/platform_data/cros_ec_proto.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'include/linux/platform_data') diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 17c2578bbc58..69801ace0496 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -419,7 +419,7 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data) return; } - if (ec_dev->mkbp_event_supported) + if (value == ACPI_NOTIFY_CROS_EC_MKBP && ec_dev->mkbp_event_supported) do { ret = cros_ec_get_next_event(ec_dev, NULL, &ec_has_more_events); diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index 701389c16fa7..3ec24f445c29 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -41,6 +41,11 @@ #define EC_MAX_REQUEST_OVERHEAD 1 #define EC_MAX_RESPONSE_OVERHEAD 32 +/* + * ACPI notify value for MKBP host event. + */ +#define ACPI_NOTIFY_CROS_EC_MKBP 0x80 + /* * EC panic is not covered by the standard (0-F) ACPI notify values. * Arbitrarily choosing B0 to notify ec panic, which is in the 84-BF -- cgit v1.2.3 From 401d07d530bfaf7131d6ab9acd32ff12b9a6ddf1 Mon Sep 17 00:00:00 2001 From: Pavan Holla Date: Tue, 31 Dec 2024 13:10:46 +0000 Subject: platform/chrome: Update ChromeOS EC header for UCSI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add EC host commands for reading and writing UCSI structures in the EC. The corresponding kernel driver is cros-ec-ucsi. Also update PD events supported by the EC. Acked-by: Tzung-Bi Shih Signed-off-by: Pavan Holla Signed-off-by: Łukasz Bartosik Link: https://lore.kernel.org/r/20241231131047.1757434-2-ukaszb@chromium.org Signed-off-by: Greg Kroah-Hartman --- include/linux/platform_data/cros_ec_commands.h | 28 +++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index b3c4993e656e..ecf290a0c98f 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -5044,8 +5044,11 @@ struct ec_response_pd_status { #define PD_EVENT_POWER_CHANGE BIT(1) #define PD_EVENT_IDENTITY_RECEIVED BIT(2) #define PD_EVENT_DATA_SWAP BIT(3) +#define PD_EVENT_TYPEC BIT(4) +#define PD_EVENT_PPM BIT(5) + struct ec_response_host_event_status { - uint32_t status; /* PD MCU host event status */ + uint32_t status; /* PD MCU host event status */ } __ec_align4; /* Set USB type-C port role and muxes */ @@ -6105,6 +6108,29 @@ struct ec_response_typec_vdm_response { #undef VDO_MAX_SIZE +/* + * UCSI OPM-PPM commands + * + * These commands are used for communication between OPM and PPM. + * Only UCSI3.0 is tested. + */ + +#define EC_CMD_UCSI_PPM_SET 0x0140 + +/* The data size is stored in the host command protocol header. */ +struct ec_params_ucsi_ppm_set { + uint16_t offset; + uint8_t data[]; +} __ec_align2; + +#define EC_CMD_UCSI_PPM_GET 0x0141 + +/* For 'GET' sub-commands, data will be returned as a raw payload. */ +struct ec_params_ucsi_ppm_get { + uint16_t offset; + uint8_t size; +} __ec_align2; + /*****************************************************************************/ /* The command range 0x200-0x2FF is reserved for Rotor. */ -- cgit v1.2.3 From b04ce63859793e3439b394976b8d29e785d4d69a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 11 Dec 2024 11:23:35 +0100 Subject: i2c: davinci: kill platform data There are no more board file users of this driver. The platform data structure is only used internally. Two of the four fields it stores are not used at all anymore. Pull the remainder into the driver data struct and shrink code by removing parts that are now dead code. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20241211102337.37956-1-brgl@bgdev.pl Signed-off-by: Andi Shyti --- drivers/i2c/busses/i2c-davinci.c | 84 +++++++------------------------ include/linux/platform_data/i2c-davinci.h | 26 ---------- 2 files changed, 19 insertions(+), 91 deletions(-) delete mode 100644 include/linux/platform_data/i2c-davinci.h (limited to 'include/linux/platform_data') diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 71dc0a6688b7..4b499931fdfd 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -26,7 +26,6 @@ #include #include #include -#include #include /* ----- global defines ----------------------------------------------- */ @@ -117,6 +116,8 @@ /* timeout for pm runtime autosuspend */ #define DAVINCI_I2C_PM_TIMEOUT 1000 /* ms */ +#define DAVINCI_I2C_DEFAULT_BUS_FREQ 100 + struct davinci_i2c_dev { struct device *dev; void __iomem *base; @@ -132,13 +133,10 @@ struct davinci_i2c_dev { #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; #endif - struct davinci_i2c_platform_data *pdata; -}; - -/* default platform data to use if not supplied in the platform_device */ -static struct davinci_i2c_platform_data davinci_i2c_platform_data_default = { - .bus_freq = 100, - .bus_delay = 0, + /* standard bus frequency (kHz) */ + unsigned int bus_freq; + /* Chip has a ICPFUNC register */ + bool has_pfunc; }; static inline void davinci_i2c_write_reg(struct davinci_i2c_dev *i2c_dev, @@ -168,7 +166,6 @@ static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) { - struct davinci_i2c_platform_data *pdata = dev->pdata; u16 psc; u32 clk; u32 d; @@ -212,16 +209,16 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) if (of_node && of_device_is_compatible(of_node, "ti,keystone-i2c")) d = 6; - clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)); + clk = ((input_clock / (psc + 1)) / (dev->bus_freq * 1000)); /* Avoid driving the bus too fast because of rounding errors above */ - if (input_clock / (psc + 1) / clk > pdata->bus_freq * 1000) + if (input_clock / (psc + 1) / clk > dev->bus_freq * 1000) clk++; /* * According to I2C-BUS Spec 2.1, in FAST-MODE LOW period should be at * least 1.3uS, which is not the case with 50% duty cycle. Driving HIGH * to LOW ratio as 1 to 2 is more safe. */ - if (pdata->bus_freq > 100) + if (dev->bus_freq > 100) clkl = (clk << 1) / 3; else clkl = (clk >> 1); @@ -255,8 +252,6 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) */ static int i2c_davinci_init(struct davinci_i2c_dev *dev) { - struct davinci_i2c_platform_data *pdata = dev->pdata; - /* put I2C into reset */ davinci_i2c_reset_ctrl(dev, 0); @@ -274,8 +269,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG)); dev_dbg(dev->dev, "CLKH = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG)); - dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n", - pdata->bus_freq, pdata->bus_delay); + dev_dbg(dev->dev, "bus_freq = %dkHz\n", dev->bus_freq); /* Take the I2C module out of reset: */ @@ -309,12 +303,6 @@ static void davinci_i2c_unprepare_recovery(struct i2c_adapter *adap) i2c_davinci_init(dev); } -static struct i2c_bus_recovery_info davinci_i2c_gpio_recovery_info = { - .recover_bus = i2c_generic_scl_recovery, - .prepare_recovery = davinci_i2c_prepare_recovery, - .unprepare_recovery = davinci_i2c_unprepare_recovery, -}; - static void davinci_i2c_set_scl(struct i2c_adapter *adap, int val) { struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); @@ -414,7 +402,6 @@ static int i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) { struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); - struct davinci_i2c_platform_data *pdata = dev->pdata; u32 flag; u16 w; unsigned long time_left; @@ -424,10 +411,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) return -EADDRNOTAVAIL; } - /* Introduce a delay, required for some boards (e.g Davinci EVM) */ - if (pdata->bus_delay) - udelay(pdata->bus_delay); - /* set the target address */ davinci_i2c_write_reg(dev, DAVINCI_I2C_SAR_REG, msg->addr); @@ -758,8 +741,8 @@ static int davinci_i2c_probe(struct platform_device *pdev) { struct davinci_i2c_dev *dev; struct i2c_adapter *adap; - struct i2c_bus_recovery_info *rinfo; int r, irq; + u32 prop; irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -773,29 +756,15 @@ static int davinci_i2c_probe(struct platform_device *pdev) dev->dev = &pdev->dev; dev->irq = irq; - dev->pdata = dev_get_platdata(&pdev->dev); platform_set_drvdata(pdev, dev); - if (!dev->pdata && pdev->dev.of_node) { - u32 prop; - - dev->pdata = devm_kzalloc(&pdev->dev, - sizeof(struct davinci_i2c_platform_data), GFP_KERNEL); - if (!dev->pdata) - return -ENOMEM; - - memcpy(dev->pdata, &davinci_i2c_platform_data_default, - sizeof(struct davinci_i2c_platform_data)); - if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &prop)) - dev->pdata->bus_freq = prop / 1000; - - dev->pdata->has_pfunc = - of_property_read_bool(pdev->dev.of_node, - "ti,has-pfunc"); - } else if (!dev->pdata) { - dev->pdata = &davinci_i2c_platform_data_default; - } + r = device_property_read_u32(&pdev->dev, "clock-frequency", &prop); + if (r) + prop = DAVINCI_I2C_DEFAULT_BUS_FREQ; + + dev->bus_freq = prop / 1000; + + dev->has_pfunc = device_property_present(&pdev->dev, "ti,has-pfunc"); dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) @@ -843,23 +812,8 @@ static int davinci_i2c_probe(struct platform_device *pdev) adap->timeout = DAVINCI_I2C_TIMEOUT; adap->dev.of_node = pdev->dev.of_node; - if (dev->pdata->has_pfunc) + if (dev->has_pfunc) adap->bus_recovery_info = &davinci_i2c_scl_recovery_info; - else if (dev->pdata->gpio_recovery) { - rinfo = &davinci_i2c_gpio_recovery_info; - adap->bus_recovery_info = rinfo; - rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", - GPIOD_OUT_HIGH_OPEN_DRAIN); - if (IS_ERR(rinfo->scl_gpiod)) { - r = PTR_ERR(rinfo->scl_gpiod); - goto err_unuse_clocks; - } - rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN); - if (IS_ERR(rinfo->sda_gpiod)) { - r = PTR_ERR(rinfo->sda_gpiod); - goto err_unuse_clocks; - } - } adap->nr = pdev->id; r = i2c_add_numbered_adapter(adap); diff --git a/include/linux/platform_data/i2c-davinci.h b/include/linux/platform_data/i2c-davinci.h deleted file mode 100644 index 98967df07468..000000000000 --- a/include/linux/platform_data/i2c-davinci.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * DaVinci I2C controller platform_device info - * - * Author: Vladimir Barinov, MontaVista Software, Inc. - * - * 2007 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. -*/ - -#ifndef __ASM_ARCH_I2C_H -#define __ASM_ARCH_I2C_H - -/* All frequencies are expressed in kHz */ -struct davinci_i2c_platform_data { - unsigned int bus_freq; /* standard bus frequency (kHz) */ - unsigned int bus_delay; /* post-transaction delay (usec) */ - bool gpio_recovery; /* Use GPIO recovery method */ - bool has_pfunc; /* Chip has a ICPFUNC register */ -}; - -/* for board setup code */ -void davinci_init_i2c(struct davinci_i2c_platform_data *); - -#endif /* __ASM_ARCH_I2C_H */ -- cgit v1.2.3 From 26769582bf353ae613f5113a1414ff3a80e08264 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Tue, 17 Dec 2024 12:11:41 -0600 Subject: mfd: syscon: Remove the platform driver support The platform driver is dead code. It is not used by DT platforms since commit bdb0066df96e ("mfd: syscon: Decouple syscon interface from platform devices") which said: For non-DT based platforms, this patch keeps syscon platform driver structure so that syscon can be probed and such non-DT based drivers can use syscon_regmap_lookup_by_pdev API and access regmap handles. Once all users of "syscon_regmap_lookup_by_pdev" migrated to DT based, we can completely remove platform driver of syscon, and keep only helper functions to get regmap handles. The last user of syscon_regmap_lookup_by_pdevname() was removed in 2018. syscon_regmap_lookup_by_pdevname() was then removed in 2019, but that commit failed to remove the rest of the platform driver. Signed-off-by: Rob Herring (Arm) Tested-by: Krzysztof Kozlowski Tested-by: Will McVicker Acked-by: Liviu Dudau Reviewed-by: Pankaj Dubey Tested-by: Pankaj Dubey Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241217-syscon-fixes-v2-2-4f56d750541d@kernel.org Signed-off-by: Lee Jones --- drivers/mfd/syscon.c | 66 ------------------------------------ drivers/mfd/vexpress-sysreg.c | 1 - include/linux/platform_data/syscon.h | 9 ----- 3 files changed, 76 deletions(-) delete mode 100644 include/linux/platform_data/syscon.h (limited to 'include/linux/platform_data') diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index 72f20de9652d..bfb1f69fcff1 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -12,22 +12,15 @@ #include #include #include -#include -#include #include #include #include #include -#include -#include -#include #include #include #include #include -static struct platform_driver syscon_driver; - static DEFINE_MUTEX(syscon_list_lock); static LIST_HEAD(syscon_list); @@ -337,62 +330,3 @@ struct regmap *syscon_regmap_lookup_by_phandle_optional(struct device_node *np, return regmap; } EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle_optional); - -static int syscon_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct syscon_platform_data *pdata = dev_get_platdata(dev); - struct syscon *syscon; - struct regmap_config syscon_config = syscon_regmap_config; - struct resource *res; - void __iomem *base; - - syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL); - if (!syscon) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; - - base = devm_ioremap(dev, res->start, resource_size(res)); - if (!base) - return -ENOMEM; - - syscon_config.max_register = resource_size(res) - 4; - if (!syscon_config.max_register) - syscon_config.max_register_is_0 = true; - - if (pdata) - syscon_config.name = pdata->label; - syscon->regmap = devm_regmap_init_mmio(dev, base, &syscon_config); - if (IS_ERR(syscon->regmap)) { - dev_err(dev, "regmap init failed\n"); - return PTR_ERR(syscon->regmap); - } - - platform_set_drvdata(pdev, syscon); - - dev_dbg(dev, "regmap %pR registered\n", res); - - return 0; -} - -static const struct platform_device_id syscon_ids[] = { - { "syscon", }, - { } -}; - -static struct platform_driver syscon_driver = { - .driver = { - .name = "syscon", - }, - .probe = syscon_probe, - .id_table = syscon_ids, -}; - -static int __init syscon_init(void) -{ - return platform_driver_register(&syscon_driver); -} -postcore_initcall(syscon_init); diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index d34d58ce46db..ef03d6cec9ff 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/include/linux/platform_data/syscon.h b/include/linux/platform_data/syscon.h deleted file mode 100644 index 2c089dd3e2bd..000000000000 --- a/include/linux/platform_data/syscon.h +++ /dev/null @@ -1,9 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef PLATFORM_DATA_SYSCON_H -#define PLATFORM_DATA_SYSCON_H - -struct syscon_platform_data { - const char *label; -}; - -#endif -- cgit v1.2.3 From 53078a736fbc60e5d3a1e14f4cd4214003815026 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Sat, 11 Jan 2025 14:01:53 +1300 Subject: HID: hid-asus: Disable OOBE mode on the ProArt P16 The new ASUS ProArt 16" laptop series come with their keyboards stuck in an Out-Of-Box-Experience mode. While in this mode most functions will not work such as LED control or Fn key combos. The correct init sequence is now done to disable this OOBE. This patch addresses only the ProArt series so far and it is unknown if there may be others, in which case a new quirk may be required. Signed-off-by: Luke D. Jones Co-developed-by: Connor Belli Signed-off-by: Connor Belli Tested-by: Jan Schmidt Signed-off-by: Jiri Kosina --- drivers/hid/hid-asus.c | 26 ++++++++++++++++++++++++++ include/linux/platform_data/x86/asus-wmi.h | 5 +++++ 2 files changed, 31 insertions(+) (limited to 'include/linux/platform_data') diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index 506c6f377e7d..46e3e42f9eb5 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -432,6 +432,26 @@ static int asus_kbd_get_functions(struct hid_device *hdev, return ret; } +static int asus_kbd_disable_oobe(struct hid_device *hdev) +{ + const u8 init[][6] = { + { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 }, + { FEATURE_KBD_REPORT_ID, 0xBA, 0xC5, 0xC4 }, + { FEATURE_KBD_REPORT_ID, 0xD0, 0x8F, 0x01 }, + { FEATURE_KBD_REPORT_ID, 0xD0, 0x85, 0xFF } + }; + int ret; + + for (size_t i = 0; i < ARRAY_SIZE(init); i++) { + ret = asus_kbd_set_report(hdev, init[i], sizeof(init[i])); + if (ret < 0) + return ret; + } + + hid_info(hdev, "Disabled OOBE for keyboard\n"); + return 0; +} + static void asus_schedule_work(struct asus_kbd_leds *led) { unsigned long flags; @@ -534,6 +554,12 @@ static int asus_kbd_register_leds(struct hid_device *hdev) ret = asus_kbd_init(hdev, FEATURE_KBD_LED_REPORT_ID2); if (ret < 0) return ret; + + if (dmi_match(DMI_PRODUCT_FAMILY, "ProArt P16")) { + ret = asus_kbd_disable_oobe(hdev); + if (ret < 0) + return ret; + } } else { /* Initialize keyboard */ ret = asus_kbd_init(hdev, FEATURE_KBD_REPORT_ID); diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 365e119bebaa..783e2a336861 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -184,6 +184,11 @@ static const struct dmi_system_id asus_use_hid_led_dmi_ids[] = { DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Flow"), }, }, + { + .matches = { + DMI_MATCH(DMI_PRODUCT_FAMILY, "ProArt P16"), + }, + }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "GA403U"), -- cgit v1.2.3