Merge branch 'openwrt:master' into master

This commit is contained in:
Hayzam Sherif 2023-03-05 11:52:05 +05:30 committed by GitHub
commit 83e41623e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
264 changed files with 4242 additions and 22825 deletions

View file

@ -1,2 +1,2 @@
LINUX_VERSION-5.15 = .94 LINUX_VERSION-5.15 = .98
LINUX_KERNEL_HASH-5.15.94 = da9270dbe64ddf1db13c70470957ff6796eb996d867bb4aed7d14a70e1c65a72 LINUX_KERNEL_HASH-5.15.98 = 7dc62cd3a45f95c9b60316a5886ea9406aee256308869dac1e4ec088fbb37787

View file

@ -8,12 +8,12 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=kexec-tools PKG_NAME:=kexec-tools
PKG_VERSION:=2.0.21 PKG_VERSION:=2.0.26
PKG_RELEASE:=2 PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@KERNEL/linux/utils/kernel/kexec PKG_SOURCE_URL:=@KERNEL/linux/utils/kernel/kexec
PKG_HASH:=e113142dee891638ad96e0f72cf9277b244477619470b30c41999d312e8e8702 PKG_HASH:=7fe36a064101cd5c515e41b2be393dce3ca88adce59d6ee668e0af7c0c4570cd
PKG_CONFIG_DEPENDS := CONFIG_KEXEC_ZLIB CONFIG_KEXEC_LZMA PKG_CONFIG_DEPENDS := CONFIG_KEXEC_ZLIB CONFIG_KEXEC_LZMA

View file

@ -1,52 +0,0 @@
From 9817ec81968a5eec7863902833fb77680544eae4 Mon Sep 17 00:00:00 2001
From: Alexander Egorenkov <egorenar-dev@posteo.net>
Date: Mon, 12 Apr 2021 13:18:05 +0200
Subject: [PATCH 1/1] arm: do not copy magic 4 bytes of appended DTB in zImage
If the passed zImage happens to have a DTB appended, then the magic 4 bytes
of the DTB are copied together with the kernel image. This leads to
failed kexec boots because the decompressor finds the aforementioned
DTB magic and falsely tries to replace the DTB passed in the register r2
with the non-existent appended one.
Signed-off-by: Alexander Egorenkov <egorenar-dev@posteo.net>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
kexec/arch/arm/kexec-zImage-arm.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
--- a/kexec/arch/arm/kexec-zImage-arm.c
+++ b/kexec/arch/arm/kexec-zImage-arm.c
@@ -382,6 +382,7 @@ int zImage_arm_load(int argc, char **arg
unsigned int atag_offset = 0x1000; /* 4k offset from memory start */
unsigned int extra_size = 0x8000; /* TEXT_OFFSET */
const struct zimage_tag *tag;
+ size_t kernel_buf_size;
size_t kernel_mem_size;
const char *command_line;
char *modified_cmdline = NULL;
@@ -538,6 +539,15 @@ int zImage_arm_load(int argc, char **arg
}
/*
+ * Save the length of the compressed kernel image w/o the appended DTB.
+ * This will be required later on when the kernel image contained
+ * in the zImage will be loaded into a kernel memory segment.
+ * And we want to load ONLY the compressed kernel image from the zImage
+ * and discard the appended DTB.
+ */
+ kernel_buf_size = len;
+
+ /*
* Always extend the zImage by four bytes to ensure that an appended
* DTB image always sees an initialised value after _edata.
*/
@@ -759,7 +769,7 @@ int zImage_arm_load(int argc, char **arg
add_segment(info, dtb_buf, dtb_length, dtb_offset, dtb_length);
}
- add_segment(info, buf, len, kernel_base, kernel_mem_size);
+ add_segment(info, buf, kernel_buf_size, kernel_base, kernel_mem_size);
info->entry = (void*)kernel_base;

View file

@ -34,6 +34,7 @@ endif
define U-Boot/Default define U-Boot/Default
BUILD_TARGET:=mediatek BUILD_TARGET:=mediatek
UBOOT_IMAGE:=u-boot-mtk.bin UBOOT_IMAGE:=u-boot-mtk.bin
HIDDEN:=1
endef endef
define U-Boot/mt7620_rfb define U-Boot/mt7620_rfb

View file

@ -68,3 +68,13 @@ define Package/mt7922bt-firmware/install
$(1)/lib/firmware/mediatek $(1)/lib/firmware/mediatek
endef endef
$(eval $(call BuildPackage,mt7922bt-firmware)) $(eval $(call BuildPackage,mt7922bt-firmware))
Package/mt7986-wo-firmware = $(call Package/firmware-default,MT7986 offload firmware)
define Package/mt7986-wo-firmware/install
$(INSTALL_DIR) $(1)/lib/firmware/mediatek
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/mediatek/mt7986_wo_0.bin \
$(PKG_BUILD_DIR)/mediatek/mt7986_wo_1.bin \
$(1)/lib/firmware/mediatek
endef
$(eval $(call BuildPackage,mt7986-wo-firmware))

View file

@ -39,7 +39,7 @@ include $(INCLUDE_DIR)/package.mk
define Package/bpf-headers define Package/bpf-headers
SECTION:=kernel SECTION:=kernel
CATEGORY:=Kernel CATEGORY:=Kernel modules
TITLE:=eBPF kernel headers TITLE:=eBPF kernel headers
BUILDONLY:=1 BUILDONLY:=1
HIDDEN:=1 HIDDEN:=1

View file

@ -1,28 +0,0 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=hwmon-gsc
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define KernelPackage/hwmon-gsc
SUBMENU:=Hardware Monitoring Support
DEPENDS:=@TARGET_imx +kmod-hwmon-core +kmod-i2c-core
TITLE:=Driver for the Gateworks System Controller
AUTOLOAD:=$(call AutoLoad,60,gsc)
FILES:=$(PKG_BUILD_DIR)/gsc.ko
endef
define KernelPackage/hwmon-gsc/description
Kernel module for the Gateworks System Controller chips.
endef
define Build/Compile
$(KERNEL_MAKE) \
M="$(PKG_BUILD_DIR)" \
EXTRA_CFLAGS="$(BUILDFLAGS)" \
modules
endef
$(eval $(call KernelPackage,hwmon-gsc))

View file

@ -1 +0,0 @@
obj-m := gsc.o

View file

@ -1,308 +0,0 @@
/*
* A hwmon driver for the Gateworks System Controller
* Copyright (C) 2009 Gateworks Corporation
*
* Author: Chris Lang <clang@gateworks.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License,
* as published by the Free Software Foundation - version 2.
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/slab.h>
#define DRV_VERSION "0.2"
enum chips { gsp };
/* AD7418 registers */
#define GSP_REG_TEMP_IN 0x00
#define GSP_REG_VIN 0x02
#define GSP_REG_3P3 0x05
#define GSP_REG_BAT 0x08
#define GSP_REG_5P0 0x0b
#define GSP_REG_CORE 0x0e
#define GSP_REG_CPU1 0x11
#define GSP_REG_CPU2 0x14
#define GSP_REG_DRAM 0x17
#define GSP_REG_EXT_BAT 0x1a
#define GSP_REG_IO1 0x1d
#define GSP_REG_IO2 0x20
#define GSP_REG_PCIE 0x23
#define GSP_REG_CURRENT 0x26
#define GSP_FAN_0 0x2C
#define GSP_FAN_1 0x2E
#define GSP_FAN_2 0x30
#define GSP_FAN_3 0x32
#define GSP_FAN_4 0x34
#define GSP_FAN_5 0x36
struct gsp_sensor_info {
const char* name;
int reg;
};
static const struct gsp_sensor_info gsp_sensors[] = {
{"temp", GSP_REG_TEMP_IN},
{"vin", GSP_REG_VIN},
{"3p3", GSP_REG_3P3},
{"bat", GSP_REG_BAT},
{"5p0", GSP_REG_5P0},
{"core", GSP_REG_CORE},
{"cpu1", GSP_REG_CPU1},
{"cpu2", GSP_REG_CPU2},
{"dram", GSP_REG_DRAM},
{"ext_bat", GSP_REG_EXT_BAT},
{"io1", GSP_REG_IO1},
{"io2", GSP_REG_IO2},
{"pci2", GSP_REG_PCIE},
{"current", GSP_REG_CURRENT},
{"fan_point0", GSP_FAN_0},
{"fan_point1", GSP_FAN_1},
{"fan_point2", GSP_FAN_2},
{"fan_point3", GSP_FAN_3},
{"fan_point4", GSP_FAN_4},
{"fan_point5", GSP_FAN_5},
};
struct gsp_data {
struct device *hwmon_dev;
struct attribute_group attrs;
enum chips type;
};
static int gsp_probe(struct i2c_client *client,
const struct i2c_device_id *id);
static int gsp_remove(struct i2c_client *client);
static const struct i2c_device_id gsp_id[] = {
{ "gsp", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, gsp_id);
static struct i2c_driver gsp_driver = {
.driver = {
.name = "gsp",
},
.probe = gsp_probe,
.remove = gsp_remove,
.id_table = gsp_id,
};
/* All registers are word-sized, except for the configuration registers.
* AD7418 uses a high-byte first convention. Do NOT use those functions to
* access the configuration registers CONF and CONF2, as they are byte-sized.
*/
static inline int gsp_read(struct i2c_client *client, u8 reg)
{
unsigned int adc = 0;
if (reg == GSP_REG_TEMP_IN || reg > GSP_REG_CURRENT)
{
adc |= i2c_smbus_read_byte_data(client, reg);
adc |= i2c_smbus_read_byte_data(client, reg + 1) << 8;
return adc;
}
else
{
adc |= i2c_smbus_read_byte_data(client, reg);
adc |= i2c_smbus_read_byte_data(client, reg + 1) << 8;
adc |= i2c_smbus_read_byte_data(client, reg + 2) << 16;
return adc;
}
}
static inline int gsp_write(struct i2c_client *client, u8 reg, u16 value)
{
i2c_smbus_write_byte_data(client, reg, value & 0xff);
i2c_smbus_write_byte_data(client, reg + 1, ((value >> 8) & 0xff));
return 1;
}
static ssize_t show_adc(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
return sprintf(buf, "%d\n", gsp_read(client, gsp_sensors[attr->index].reg));
}
static ssize_t show_label(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
return sprintf(buf, "%s\n", gsp_sensors[attr->index].name);
}
static ssize_t store_fan(struct device *dev,
struct device_attribute *devattr, const char *buf, size_t count)
{
u16 val;
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
val = simple_strtoul(buf, NULL, 10);
gsp_write(client, gsp_sensors[attr->index].reg, val);
return count;
}
static SENSOR_DEVICE_ATTR(temp0_input, S_IRUGO, show_adc, NULL, 0);
static SENSOR_DEVICE_ATTR(temp0_label, S_IRUGO, show_label, NULL, 0);
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_adc, NULL, 1);
static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_label, NULL, 1);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_adc, NULL, 2);
static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_label, NULL, 2);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 3);
static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_label, NULL, 3);
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 4);
static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 4);
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 5);
static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_label, NULL, 5);
static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_adc, NULL, 6);
static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_label, NULL, 6);
static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_adc, NULL, 7);
static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_label, NULL, 7);
static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_adc, NULL, 8);
static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 8);
static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_adc, NULL, 9);
static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 9);
static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_adc, NULL, 10);
static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 10);
static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_adc, NULL, 11);
static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_label, NULL, 11);
static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_adc, NULL, 12);
static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_label, NULL, 12);
static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_adc, NULL, 13);
static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_label, NULL, 13);
static SENSOR_DEVICE_ATTR(fan0_point0, S_IRUGO | S_IWUSR, show_adc, store_fan, 14);
static SENSOR_DEVICE_ATTR(fan0_point1, S_IRUGO | S_IWUSR, show_adc, store_fan, 15);
static SENSOR_DEVICE_ATTR(fan0_point2, S_IRUGO | S_IWUSR, show_adc, store_fan, 16);
static SENSOR_DEVICE_ATTR(fan0_point3, S_IRUGO | S_IWUSR, show_adc, store_fan, 17);
static SENSOR_DEVICE_ATTR(fan0_point4, S_IRUGO | S_IWUSR, show_adc, store_fan, 18);
static SENSOR_DEVICE_ATTR(fan0_point5, S_IRUGO | S_IWUSR, show_adc, store_fan, 19);
static struct attribute *gsp_attributes[] = {
&sensor_dev_attr_temp0_input.dev_attr.attr,
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
&sensor_dev_attr_in3_input.dev_attr.attr,
&sensor_dev_attr_in4_input.dev_attr.attr,
&sensor_dev_attr_in5_input.dev_attr.attr,
&sensor_dev_attr_in6_input.dev_attr.attr,
&sensor_dev_attr_in7_input.dev_attr.attr,
&sensor_dev_attr_in8_input.dev_attr.attr,
&sensor_dev_attr_in9_input.dev_attr.attr,
&sensor_dev_attr_in10_input.dev_attr.attr,
&sensor_dev_attr_in11_input.dev_attr.attr,
&sensor_dev_attr_in12_input.dev_attr.attr,
&sensor_dev_attr_temp0_label.dev_attr.attr,
&sensor_dev_attr_in0_label.dev_attr.attr,
&sensor_dev_attr_in1_label.dev_attr.attr,
&sensor_dev_attr_in2_label.dev_attr.attr,
&sensor_dev_attr_in3_label.dev_attr.attr,
&sensor_dev_attr_in4_label.dev_attr.attr,
&sensor_dev_attr_in5_label.dev_attr.attr,
&sensor_dev_attr_in6_label.dev_attr.attr,
&sensor_dev_attr_in7_label.dev_attr.attr,
&sensor_dev_attr_in8_label.dev_attr.attr,
&sensor_dev_attr_in9_label.dev_attr.attr,
&sensor_dev_attr_in10_label.dev_attr.attr,
&sensor_dev_attr_in11_label.dev_attr.attr,
&sensor_dev_attr_in12_label.dev_attr.attr,
&sensor_dev_attr_fan0_point0.dev_attr.attr,
&sensor_dev_attr_fan0_point1.dev_attr.attr,
&sensor_dev_attr_fan0_point2.dev_attr.attr,
&sensor_dev_attr_fan0_point3.dev_attr.attr,
&sensor_dev_attr_fan0_point4.dev_attr.attr,
&sensor_dev_attr_fan0_point5.dev_attr.attr,
NULL
};
static int gsp_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
struct gsp_data *data;
int err;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA)) {
err = -EOPNOTSUPP;
goto exit;
}
if (!(data = kzalloc(sizeof(struct gsp_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->type = id->driver_data;
switch (data->type) {
case 0:
data->attrs.attrs = gsp_attributes;
break;
}
dev_info(&client->dev, "%s chip found\n", client->name);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &data->attrs);
exit_free:
kfree(data);
exit:
return err;
}
static int gsp_remove(struct i2c_client *client)
{
struct gsp_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &data->attrs);
kfree(data);
return 0;
}
static int __init gsp_init(void)
{
return i2c_add_driver(&gsp_driver);
}
static void __exit gsp_exit(void)
{
i2c_del_driver(&gsp_driver);
}
module_init(gsp_init);
module_exit(gsp_exit);
MODULE_AUTHOR("Chris Lang <clang@gateworks.com>");
MODULE_DESCRIPTION("GSC HWMON driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);

View file

@ -108,6 +108,25 @@ endef
$(eval $(call KernelPackage,hwmon-drivetemp)) $(eval $(call KernelPackage,hwmon-drivetemp))
define KernelPackage/hwmon-gsc
TITLE:=Gateworks System Controller support
KCONFIG:=CONFIG_MFD_GATEWORKS_GSC \
CONFIG_SENSORS_GSC
FILES:= \
$(LINUX_DIR)/drivers/mfd/gateworks-gsc.ko \
$(LINUX_DIR)/drivers/hwmon/gsc-hwmon.ko
AUTOLOAD:=$(call AutoLoad,20,gsc-hwmon,1)
$(call AddDepends/hwmon,+kmod-i2c-core)
endef
define KernelPackage/hwmon-gsc/description
Kernel module for Gateworks System Controller with temperature sensor,
ADCs, and FAN controller
endef
$(eval $(call KernelPackage,hwmon-gsc))
define KernelPackage/hwmon-gpiofan define KernelPackage/hwmon-gpiofan
TITLE:=Generic GPIO FAN support TITLE:=Generic GPIO FAN support
KCONFIG:=CONFIG_SENSORS_GPIO_FAN KCONFIG:=CONFIG_SENSORS_GPIO_FAN

View file

@ -115,6 +115,23 @@ endef
$(eval $(call KernelPackage,ledtrig-pattern)) $(eval $(call KernelPackage,ledtrig-pattern))
define KernelPackage/ledtrig-tty
SUBMENU:=$(LEDS_MENU)
TITLE:=LED Trigger for TTY devices
DEPENDS:=@LINUX_5_15
KCONFIG:=CONFIG_LEDS_TRIGGER_TTY
FILES:=$(LED_TRIGGER_DIR)/ledtrig-tty.ko
AUTOLOAD:=$(call AutoLoad,50,ledtrig-tty)
endef
define KernelPackage/ledtrig-tty/description
This allows LEDs to be controlled by activity on ttys which includes
serial devices like '/dev/ttyS0'.
endef
$(eval $(call KernelPackage,ledtrig-tty))
define KernelPackage/leds-apu define KernelPackage/leds-apu
SUBMENU:=$(LEDS_MENU) SUBMENU:=$(LEDS_MENU)
TITLE:=PC Engines APU1 LED support TITLE:=PC Engines APU1 LED support

View file

@ -82,7 +82,7 @@
help help
--- a/local-symbols --- a/local-symbols
+++ b/local-symbols +++ b/local-symbols
@@ -110,6 +110,7 @@ ADM8211= @@ -102,6 +102,7 @@ ADM8211=
ATH_COMMON= ATH_COMMON=
WLAN_VENDOR_ATH= WLAN_VENDOR_ATH=
ATH_DEBUG= ATH_DEBUG=

View file

@ -37,7 +37,7 @@
void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature); void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
--- a/local-symbols --- a/local-symbols
+++ b/local-symbols +++ b/local-symbols
@@ -169,6 +169,7 @@ ATH10K_SNOC= @@ -161,6 +161,7 @@ ATH10K_SNOC=
ATH10K_DEBUG= ATH10K_DEBUG=
ATH10K_DEBUGFS= ATH10K_DEBUGFS=
ATH10K_SPECTRAL= ATH10K_SPECTRAL=

View file

@ -114,7 +114,7 @@ v13:
ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o
--- a/local-symbols --- a/local-symbols
+++ b/local-symbols +++ b/local-symbols
@@ -170,6 +170,7 @@ ATH10K_DEBUG= @@ -162,6 +162,7 @@ ATH10K_DEBUG=
ATH10K_DEBUGFS= ATH10K_DEBUGFS=
ATH10K_SPECTRAL= ATH10K_SPECTRAL=
ATH10K_THERMAL= ATH10K_THERMAL=

View file

@ -371,7 +371,7 @@
--- a/local-symbols --- a/local-symbols
+++ b/local-symbols +++ b/local-symbols
@@ -137,6 +137,7 @@ ATH9K_WOW= @@ -129,6 +129,7 @@ ATH9K_WOW=
ATH9K_RFKILL= ATH9K_RFKILL=
ATH9K_CHANNEL_CONTEXT= ATH9K_CHANNEL_CONTEXT=
ATH9K_PCOEM= ATH9K_PCOEM=

View file

@ -1,6 +1,6 @@
--- a/local-symbols --- a/local-symbols
+++ b/local-symbols +++ b/local-symbols
@@ -354,6 +354,7 @@ RT2X00_LIB_FIRMWARE= @@ -347,6 +347,7 @@ RT2X00_LIB_FIRMWARE=
RT2X00_LIB_CRYPTO= RT2X00_LIB_CRYPTO=
RT2X00_LIB_LEDS= RT2X00_LIB_LEDS=
RT2X00_LIB_DEBUGFS= RT2X00_LIB_DEBUGFS=

View file

@ -90,7 +90,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
#include "driver-ops.h" #include "driver-ops.h"
static int mesh_allocated; static int mesh_allocated;
@@ -698,6 +699,102 @@ ieee80211_mesh_update_bss_params(struct @@ -698,6 +699,95 @@ ieee80211_mesh_update_bss_params(struct
__le32_to_cpu(he_oper->he_oper_params); __le32_to_cpu(he_oper->he_oper_params);
} }
@ -137,8 +137,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ if (!entry) + if (!entry)
+ return false; + return false;
+ +
+ if (skb_headroom(skb) + 2 * ETH_ALEN < entry->hdrlen + + if (skb_headroom(skb) < entry->hdrlen + entry->fast_tx.hdr_len)
+ entry->fast_tx.hdr_len)
+ return false; + return false;
+ +
+ sta = rcu_dereference(entry->mpath->next_hop); + sta = rcu_dereference(entry->mpath->next_hop);
@ -154,16 +153,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ tid_tx->last_tx = jiffies; + tid_tx->last_tx = jiffies;
+ } + }
+ +
+ /* If the skb is shared we need to obtain our own copy */ + skb = skb_share_check(skb, GFP_ATOMIC);
+ if (skb_shared(skb)) { + if (!skb)
+ struct sk_buff *oskb = skb; + return true;
+
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (!skb)
+ return false;
+
+ kfree_skb(oskb);
+ }
+ +
+ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb)); + skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
+ +
@ -184,6 +176,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ if (copy_sa) + if (copy_sa)
+ ether_addr_copy(meshhdr->eaddr2, sa); + ether_addr_copy(meshhdr->eaddr2, sa);
+ +
+ skb_push(skb, 2 * ETH_ALEN);
+ __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx, + __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx,
+ entry->mpath->dst, sdata->vif.addr); + entry->mpath->dst, sdata->vif.addr);
+ +
@ -193,7 +186,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
/** /**
* ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
* @hdr: 802.11 frame header * @hdr: 802.11 frame header
@@ -780,6 +877,8 @@ static void ieee80211_mesh_housekeeping( @@ -780,6 +870,8 @@ static void ieee80211_mesh_housekeeping(
changed = mesh_accept_plinks_update(sdata); changed = mesh_accept_plinks_update(sdata);
ieee80211_mbss_info_change_notify(sdata, changed); ieee80211_mbss_info_change_notify(sdata, changed);
@ -566,7 +559,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ if (!entry) + if (!entry)
+ goto unlock_sta; + goto unlock_sta;
+ +
+ spin_lock_bh(&cache->walk_lock); + spin_lock(&cache->walk_lock);
+ prev = rhashtable_lookup_get_insert_fast(&cache->rht, + prev = rhashtable_lookup_get_insert_fast(&cache->rht,
+ &entry->rhash, + &entry->rhash,
+ fast_tx_rht_params); + fast_tx_rht_params);
@ -589,7 +582,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ hlist_add_head(&entry->walk_list, &cache->walk_head); + hlist_add_head(&entry->walk_list, &cache->walk_head);
+ +
+unlock_cache: +unlock_cache:
+ spin_unlock_bh(&cache->walk_lock); + spin_unlock(&cache->walk_lock);
+unlock_sta: +unlock_sta:
+ spin_unlock_bh(&sta->lock); + spin_unlock_bh(&sta->lock);
+} +}
@ -771,28 +764,20 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
@@ -3645,8 +3652,6 @@ static void __ieee80211_xmit_fast(struct @@ -3646,7 +3653,6 @@ static void __ieee80211_xmit_fast(struct
struct ieee80211_tx_data tx;
ieee80211_tx_result r; ieee80211_tx_result r;
int hw_headroom = sdata->local->hw.extra_tx_headroom; int hw_headroom = sdata->local->hw.extra_tx_headroom;
- int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2); int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
- struct ethhdr eth; - struct ethhdr eth;
skb = skb_share_check(skb, GFP_ATOMIC); skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb)) if (unlikely(!skb))
@@ -3661,16 +3666,15 @@ static void __ieee80211_xmit_fast(struct @@ -3666,11 +3672,10 @@ static void __ieee80211_xmit_fast(struct
* more room than we already have in 'extra_head'
*/
if (unlikely(ieee80211_skb_resize(sdata, skb,
- max_t(int, extra_head + hw_headroom -
+ max_t(int, fast_tx->hdr_len + hw_headroom -
skb_headroom(skb), 0),
ENCRYPT_NO))) ENCRYPT_NO)))
goto free; goto free;
- memcpy(&eth, skb->data, ETH_HLEN - 2); - memcpy(&eth, skb->data, ETH_HLEN - 2);
- hdr = skb_push(skb, extra_head); hdr = skb_push(skb, extra_head);
+ hdr = skb_push(skb, fast_tx->hdr_len);
memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len); memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len);
- memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN); - memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN);
- memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN); - memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN);
@ -801,16 +786,17 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
@@ -3689,7 +3693,7 @@ static void __ieee80211_xmit_fast(struct @@ -3689,7 +3694,8 @@ static void __ieee80211_xmit_fast(struct
#endif #endif
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
- tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; - tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+ u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; + u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+
*ieee80211_get_qos_ctl(hdr) = tid; *ieee80211_get_qos_ctl(hdr) = tid;
} }
@@ -3732,6 +3736,7 @@ static bool ieee80211_xmit_fast(struct i @@ -3732,6 +3738,7 @@ static bool ieee80211_xmit_fast(struct i
struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
struct tid_ampdu_tx *tid_tx = NULL; struct tid_ampdu_tx *tid_tx = NULL;
struct sk_buff *next; struct sk_buff *next;
@ -818,17 +804,16 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
u8 tid = IEEE80211_NUM_TIDS; u8 tid = IEEE80211_NUM_TIDS;
/* control port protocol needs a lot of special handling */ /* control port protocol needs a lot of special handling */
@@ -3757,14 +3762,18 @@ static bool ieee80211_xmit_fast(struct i @@ -3757,6 +3764,8 @@ static bool ieee80211_xmit_fast(struct i
} }
} }
+ memcpy(&eth, skb->data, ETH_HLEN - 2); + memcpy(&eth, skb->data, ETH_HLEN - 2);
+ +
/* after this point (skb is modified) we cannot return false */ /* after this point (skb is modified) we cannot return false */
+ skb_pull(skb, ETH_HLEN - 2);
skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata)); skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
if (!skb) if (!skb)
return true; @@ -3764,7 +3773,8 @@ static bool ieee80211_xmit_fast(struct i
skb_list_walk_safe(skb, skb, next) { skb_list_walk_safe(skb, skb, next) {
skb_mark_not_on_list(skb); skb_mark_not_on_list(skb);
@ -838,7 +823,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
} }
return true; return true;
@@ -4244,8 +4253,15 @@ void __ieee80211_subif_start_xmit(struct @@ -4244,8 +4254,15 @@ void __ieee80211_subif_start_xmit(struct
return; return;
} }
@ -854,7 +839,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
goto out_free; goto out_free;
@@ -4255,8 +4271,6 @@ void __ieee80211_subif_start_xmit(struct @@ -4255,8 +4272,6 @@ void __ieee80211_subif_start_xmit(struct
skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb)); skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
ieee80211_aggr_check(sdata, sta, skb); ieee80211_aggr_check(sdata, sta, skb);

View file

@ -64,7 +64,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ +
+ skb->dev = sdata->dev; + skb->dev = sdata->dev;
+ memcpy(&eth, skb->data, ETH_HLEN - 2); + memcpy(&eth, skb->data, ETH_HLEN - 2);
+ skb_pull(skb, sizeof(eth)); + skb_pull(skb, 2);
+ __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx, + __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx,
+ eth.h_dest, eth.h_source); + eth.h_dest, eth.h_source);
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); + IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);

View file

@ -0,0 +1,68 @@
From: Muna Sinada <quic_msinada@quicinc.com>
Date: Wed, 5 Oct 2022 14:54:45 -0700
Subject: [PATCH] wifi: mac80211: Add VHT MU-MIMO related flags in
ieee80211_bss_conf
Adding flags for SU Beamformer, SU Beamformee, MU Beamformer and
MU Beamformee for VHT. This is utilized to pass MU-MIMO
configurations from user space to driver in AP mode.
Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
Link: https://lore.kernel.org/r/1665006886-23874-1-git-send-email-quic_msinada@quicinc.com
[fixed indentation, removed redundant !!]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -653,6 +653,14 @@ struct ieee80211_fils_discovery {
* write-protected by sdata_lock and local->mtx so holding either is fine
* for read access.
* @color_change_color: the bss color that will be used after the change.
+ * @vht_su_beamformer: in AP mode, does this BSS support operation as an VHT SU
+ * beamformer
+ * @vht_su_beamformee: in AP mode, does this BSS support operation as an VHT SU
+ * beamformee
+ * @vht_mu_beamformer: in AP mode, does this BSS support operation as an VHT MU
+ * beamformer
+ * @vht_mu_beamformee: in AP mode, does this BSS support operation as an VHT MU
+ * beamformee
*/
struct ieee80211_bss_conf {
const u8 *bssid;
@@ -726,6 +734,11 @@ struct ieee80211_bss_conf {
bool color_change_active;
u8 color_change_color;
+
+ bool vht_su_beamformer;
+ bool vht_su_beamformee;
+ bool vht_mu_beamformer;
+ bool vht_mu_beamformee;
};
/**
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1251,6 +1251,21 @@ static int ieee80211_start_ap(struct wip
prev_beacon_int = link_conf->beacon_int;
link_conf->beacon_int = params->beacon_interval;
+ if (params->vht_cap) {
+ link_conf->vht_su_beamformer =
+ params->vht_cap->vht_cap_info &
+ cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
+ link_conf->vht_su_beamformee =
+ params->vht_cap->vht_cap_info &
+ cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
+ link_conf->vht_mu_beamformer =
+ params->vht_cap->vht_cap_info &
+ cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
+ link_conf->vht_mu_beamformee =
+ params->vht_cap->vht_cap_info &
+ cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
+ }
+
if (params->he_cap && params->he_oper) {
link_conf->he_support = true;
link_conf->htc_trig_based_pkt_ext =

View file

@ -0,0 +1,68 @@
From: Muna Sinada <quic_msinada@quicinc.com>
Date: Wed, 5 Oct 2022 14:54:46 -0700
Subject: [PATCH] wifi: mac80211: Add HE MU-MIMO related flags in
ieee80211_bss_conf
Adding flags for SU Beamformer, SU Beamformee, MU Beamformer and Full
Bandwidth UL MU-MIMO for HE. This is utilized to pass MU-MIMO
configurations from user space to driver in AP mode.
Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
Link: https://lore.kernel.org/r/1665006886-23874-2-git-send-email-quic_msinada@quicinc.com
[fixed indentation, removed redundant !!]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -661,6 +661,15 @@ struct ieee80211_fils_discovery {
* beamformer
* @vht_mu_beamformee: in AP mode, does this BSS support operation as an VHT MU
* beamformee
+ * @he_su_beamformer: in AP-mode, does this BSS support operation as an HE SU
+ * beamformer
+ * @he_su_beamformee: in AP-mode, does this BSS support operation as an HE SU
+ * beamformee
+ * @he_mu_beamformer: in AP-mode, does this BSS support operation as an HE MU
+ * beamformer
+ * @he_full_ul_mumimo: does this BSS support the reception (AP) or transmission
+ * (non-AP STA) of an HE TB PPDU on an RU that spans the entire PPDU
+ * bandwidth
*/
struct ieee80211_bss_conf {
const u8 *bssid;
@@ -739,6 +748,10 @@ struct ieee80211_bss_conf {
bool vht_su_beamformee;
bool vht_mu_beamformer;
bool vht_mu_beamformee;
+ bool he_su_beamformer;
+ bool he_su_beamformee;
+ bool he_mu_beamformer;
+ bool he_full_ul_mumimo;
};
/**
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1280,6 +1280,21 @@ static int ieee80211_start_ap(struct wip
changed |= BSS_CHANGED_HE_BSS_COLOR;
}
+ if (params->he_cap) {
+ link_conf->he_su_beamformer =
+ params->he_cap->phy_cap_info[3] &
+ IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
+ link_conf->he_su_beamformee =
+ params->he_cap->phy_cap_info[4] &
+ IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE;
+ link_conf->he_mu_beamformer =
+ params->he_cap->phy_cap_info[4] &
+ IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
+ link_conf->he_full_ul_mumimo =
+ params->he_cap->phy_cap_info[2] &
+ IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
+ }
+
if (sdata->vif.type == NL80211_IFTYPE_AP &&
params->mbssid_config.tx_wdev) {
err = ieee80211_set_ap_mbssid_options(sdata,

View file

@ -0,0 +1,60 @@
From: Ryder Lee <ryder.lee@mediatek.com>
Date: Sat, 18 Feb 2023 01:50:05 +0800
Subject: [PATCH] wifi: mac80211: introduce
ieee80211_refresh_tx_agg_session_timer()
This allows low level drivers to refresh the tx agg session timer, based on
querying stats from the firmware usually. Especially for some mt76 devices
support .net_fill_forward_path would bypass mac80211, which leads to tx BA
session timeout for certain clients.
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -5968,6 +5968,18 @@ void ieee80211_queue_delayed_work(struct
unsigned long delay);
/**
+ * ieee80211_refresh_tx_agg_session_timer - Refresh a tx agg session timer.
+ * @sta: the station for which to start a BA session
+ * @tid: the TID to BA on.
+ *
+ * This function allows low level driver to refresh tx agg session timer
+ * to maintain BA session, the session level will still be managed by the
+ * mac80211.
+ */
+void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *sta,
+ u16 tid);
+
+/**
* ieee80211_start_tx_ba_session - Start a tx Block Ack session.
* @sta: the station for which to start a BA session
* @tid: the TID to BA on.
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -552,6 +552,23 @@ void ieee80211_tx_ba_session_handle_star
ieee80211_send_addba_with_timeout(sta, tid_tx);
}
+void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *pubsta,
+ u16 tid)
+{
+ struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
+ struct tid_ampdu_tx *tid_tx;
+
+ if (WARN_ON_ONCE(tid >= IEEE80211_NUM_TIDS))
+ return;
+
+ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
+ if (!tid_tx)
+ return;
+
+ tid_tx->last_tx = jiffies;
+}
+EXPORT_SYMBOL(ieee80211_refresh_tx_agg_session_timer);
+
/*
* After accepting the AddBA Response we activated a timer,
* resetting it after each frame that we send.

View file

@ -0,0 +1,77 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Thu, 2 Mar 2023 13:52:29 +0100
Subject: [PATCH] wifi: mac80211: add mesh fast-rx support
This helps bring down rx CPU usage by avoiding calls to the rx handlers in
the slow path. Supports forwarding and local rx, including A-MSDU.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4572,6 +4572,12 @@ void ieee80211_check_fast_rx(struct sta_
}
break;
+ case NL80211_IFTYPE_MESH_POINT:
+ fastrx.expected_ds_bits = cpu_to_le16(IEEE80211_FCTL_FROMDS |
+ IEEE80211_FCTL_TODS);
+ fastrx.da_offs = offsetof(struct ieee80211_hdr, addr3);
+ fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
+ break;
default:
goto clear;
}
@@ -4780,6 +4786,7 @@ static bool ieee80211_invoke_fast_rx(str
struct sk_buff *skb = rx->skb;
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ static ieee80211_rx_result res;
int orig_len = skb->len;
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
int snap_offs = hdrlen;
@@ -4841,7 +4848,8 @@ static bool ieee80211_invoke_fast_rx(str
snap_offs += IEEE80211_CCMP_HDR_LEN;
}
- if (!(status->rx_flags & IEEE80211_RX_AMSDU)) {
+ if (!ieee80211_vif_is_mesh(&rx->sdata->vif) &&
+ !(status->rx_flags & IEEE80211_RX_AMSDU)) {
if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
return false;
@@ -4880,13 +4888,29 @@ static bool ieee80211_invoke_fast_rx(str
/* do the header conversion - first grab the addresses */
ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs);
ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs);
- skb_postpull_rcsum(skb, skb->data + snap_offs,
- sizeof(rfc1042_header) + 2);
- /* remove the SNAP but leave the ethertype */
- skb_pull(skb, snap_offs + sizeof(rfc1042_header));
+ if (ieee80211_vif_is_mesh(&rx->sdata->vif)) {
+ skb_pull(skb, snap_offs - 2);
+ put_unaligned_be16(skb->len - 2, skb->data);
+ } else {
+ skb_postpull_rcsum(skb, skb->data + snap_offs,
+ sizeof(rfc1042_header) + 2);
+
+ /* remove the SNAP but leave the ethertype */
+ skb_pull(skb, snap_offs + sizeof(rfc1042_header));
+ }
/* push the addresses in front */
memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs));
+ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
+ switch (res) {
+ case RX_QUEUED:
+ return true;
+ case RX_CONTINUE:
+ break;
+ default:
+ goto drop;
+ }
+
ieee80211_rx_8023(rx, fast_rx, orig_len);
return true;

View file

@ -8,9 +8,9 @@ PKG_LICENSE_FILES:=
PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_URL:=https://github.com/openwrt/mt76
PKG_SOURCE_PROTO:=git PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2023-02-02 PKG_SOURCE_DATE:=2023-03-01
PKG_SOURCE_VERSION:=b2360d59747c6fed2b65bc1c3563c10593c83f3e PKG_SOURCE_VERSION:=c32d6d849c43792abd8007e13e468b12d6d6e0b7
PKG_MIRROR_HASH:=f85f00fa8f549de348a115f92c4f0235e413ed924669aece390c7570882526dd PKG_MIRROR_HASH:=b7004bc920ba44cef2f7868d94beb2d288ff9d399af624ce5dad972f953723c8
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name> PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_USE_NINJA:=0 PKG_USE_NINJA:=0

View file

@ -5,11 +5,11 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=dtc PKG_NAME:=dtc
PKG_VERSION:=1.6.1 PKG_VERSION:=1.7.0
PKG_RELEASE:=$(AUTORELEASE) PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_HASH:=65cec529893659a49a89740bb362f507a3b94fc8cd791e76a8d6a2b6f3203473 PKG_HASH:=29edce3d302a15563d8663198bbc398c5a0554765c83830d0d4c0409d21a16c4
PKG_SOURCE_URL:=@KERNEL/software/utils/dtc PKG_SOURCE_URL:=@KERNEL/software/utils/dtc
PKG_MAINTAINER:=Yousong Zhou <yszhou4tech@gmail.com> PKG_MAINTAINER:=Yousong Zhou <yszhou4tech@gmail.com>

View file

@ -1,137 +0,0 @@
From 17739b7ef510917471409d71fb45d8eaf6a1e1fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Thu, 9 Dec 2021 07:14:20 +0100
Subject: [PATCH] Support 'r' format for printing raw bytes with fdtget
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
FT is sometimes used for storing raw data. That is quite common for
U-Boot FIT images.
Extracting such data is not trivial currently. Using type 's' (string)
will replace every 0x00 (NUL) with 0x20 (space). Using type 'x' will
print bytes but in xxd incompatible format.
This commit adds support for 'r' (raw) format. Example usage:
fdtget -t r firmware.itb /images/foo data > image.raw
Support for encoding isn't added as there isn't any clean way of passing
binary data as command line argument.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Message-Id: <20211209061420.29466-1-zajec5@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
Documentation/manual.txt | 2 +-
fdtget.c | 5 +++++
fdtput.c | 2 ++
tests/run_tests.sh | 2 ++
tests/utilfdt_test.c | 5 ++++-
util.c | 4 ++--
util.h | 3 ++-
7 files changed, 18 insertions(+), 5 deletions(-)
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -712,7 +712,7 @@ The syntax of the fdtget command is:
where options are:
- <type> s=string, i=int, u=unsigned, x=hex
+ <type> s=string, i=int, u=unsigned, x=hex, r=raw
Optional modifier prefix:
hh or b=byte, h=2 byte, l=4 byte (default)
--- a/fdtget.c
+++ b/fdtget.c
@@ -91,6 +91,11 @@ static int show_data(struct display_info
if (len == 0)
return 0;
+ if (disp->type == 'r') {
+ fwrite(data, 1, len, stdout);
+ return 0;
+ }
+
is_string = (disp->type) == 's' ||
(!disp->type && util_is_printable_string(data, len));
if (is_string) {
--- a/fdtput.c
+++ b/fdtput.c
@@ -433,6 +433,8 @@ int main(int argc, char *argv[])
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
usage("Invalid type string");
+ if (disp.type == 'r')
+ usage("Unsupported raw data type");
break;
case 'v':
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -852,6 +852,8 @@ fdtget_tests () {
run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size
run_fdtget_test "61 62 63 0" -tbx $dtb /randomnode tricky1
run_fdtget_test "a b c d de ea ad be ef" -tbx $dtb /randomnode blob
+ run_fdtget_test "MyBoardName\0MyBoardFamilyName\0" -tr $dtb / compatible
+ run_fdtget_test "\x0a\x0b\x0c\x0d\xde\xea\xad\xbe\xef" -tr $dtb /randomnode blob
# Here the property size is not a multiple of 4 bytes, so it should fail
run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed
--- a/tests/utilfdt_test.c
+++ b/tests/utilfdt_test.c
@@ -73,6 +73,9 @@ static void check_sizes(char *modifier,
*ptr = 's';
check(fmt, 's', -1);
+
+ *ptr = 'r';
+ check(fmt, 'r', -1);
}
static void test_utilfdt_decode_type(void)
@@ -90,7 +93,7 @@ static void test_utilfdt_decode_type(voi
/* try every other character */
checkfail("");
for (ch = ' '; ch < 127; ch++) {
- if (!strchr("iuxs", ch)) {
+ if (!strchr("iuxsr", ch)) {
*fmt = ch;
fmt[1] = '\0';
checkfail(fmt);
--- a/util.c
+++ b/util.c
@@ -353,11 +353,11 @@ int utilfdt_decode_type(const char *fmt,
}
/* we should now have a type */
- if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+ if ((*fmt == '\0') || !strchr("iuxsr", *fmt))
return -1;
/* convert qualifier (bhL) to byte size */
- if (*fmt != 's')
+ if (*fmt != 's' && *fmt != 'r')
*size = qualifier == 'b' ? 1 :
qualifier == 'h' ? 2 :
qualifier == 'l' ? 4 : -1;
--- a/util.h
+++ b/util.h
@@ -143,6 +143,7 @@ int utilfdt_write_err(const char *filena
* i signed integer
* u unsigned integer
* x hex
+ * r raw
*
* TODO: Implement ll modifier (8 bytes)
* TODO: Implement o type (octal)
@@ -160,7 +161,7 @@ int utilfdt_decode_type(const char *fmt,
*/
#define USAGE_TYPE_MSG \
- "<type>\ts=string, i=int, u=unsigned, x=hex\n" \
+ "<type>\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \
"\tOptional modifier prefix:\n" \
"\t\thh or b=byte, h=2 byte, l=4 byte (default)";

View file

@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=fritz-tools PKG_NAME:=fritz-tools
PKG_RELEASE:=1 PKG_RELEASE:=2
CMAKE_INSTALL:=1 CMAKE_INSTALL:=1
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk

View file

@ -210,7 +210,7 @@ int main(int argc, char **argv)
if (argc > 1 && optind <= argc) { if (argc > 1 && optind <= argc) {
in = fopen(argv[optind], "r"); in = fopen(argv[optind], "r");
if (!in) { if (!in) {
perror("Failed to create output file"); perror("Failed to open input file");
goto out_bad; goto out_bad;
} }
} }
@ -253,7 +253,9 @@ out_bad:
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
out: out:
fclose(in); if (in)
fclose(out); fclose(in);
if (out)
fclose(out);
return ret; return ret;
} }

View file

@ -258,7 +258,7 @@ SVN-Revision: 35130
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/icmpv6.h> #include <linux/icmpv6.h>
@@ -943,10 +944,10 @@ static void tcp_v6_send_response(const s @@ -944,10 +945,10 @@ static void tcp_v6_send_response(const s
topt = (__be32 *)(t1 + 1); topt = (__be32 *)(t1 + 1);
if (tsecr) { if (tsecr) {

View file

@ -1123,7 +1123,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
} }
--- a/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c
@@ -5585,7 +5585,7 @@ static void port_event(struct usb_hub *h @@ -5584,7 +5584,7 @@ static void port_event(struct usb_hub *h
port_dev->over_current_count++; port_dev->over_current_count++;
port_over_current_notify(port_dev); port_over_current_notify(port_dev);

View file

@ -12,7 +12,7 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -3554,6 +3554,13 @@ N: bcm113* @@ -3555,6 +3555,13 @@ N: bcm113*
N: bcm216* N: bcm216*
N: kona N: kona

View file

@ -33,7 +33,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
#define USB_VENDOR_ID_BELKIN 0x050d #define USB_VENDOR_ID_BELKIN 0x050d
#define USB_DEVICE_ID_FLIP_KVM 0x3201 #define USB_DEVICE_ID_FLIP_KVM 0x3201
@@ -1315,6 +1318,9 @@ @@ -1316,6 +1319,9 @@
#define USB_VENDOR_ID_XAT 0x2505 #define USB_VENDOR_ID_XAT 0x2505
#define USB_DEVICE_ID_XAT_CSR 0x0220 #define USB_DEVICE_ID_XAT_CSR 0x0220

View file

@ -90,7 +90,7 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+... +...
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -3554,6 +3554,13 @@ N: bcm113* @@ -3555,6 +3555,13 @@ N: bcm113*
N: bcm216* N: bcm216*
N: kona N: kona

View file

@ -28,7 +28,7 @@ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -3562,7 +3562,7 @@ F: Documentation/devicetree/bindings/med @@ -3563,7 +3563,7 @@ F: Documentation/devicetree/bindings/med
F: drivers/staging/media/rpivid F: drivers/staging/media/rpivid
BROADCOM BCM2835 CAMERA DRIVER BROADCOM BCM2835 CAMERA DRIVER

View file

@ -31,7 +31,7 @@ Reported-by: kbuild test robot <lkp@intel.com>
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -3566,7 +3566,7 @@ M: Raspberry Pi Kernel Maintenance <kern @@ -3567,7 +3567,7 @@ M: Raspberry Pi Kernel Maintenance <kern
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
F: drivers/media/platform/bcm2835/ F: drivers/media/platform/bcm2835/

View file

@ -25,7 +25,7 @@ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -17529,6 +17529,14 @@ T: git git://linuxtv.org/media_tree.git @@ -17530,6 +17530,14 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
F: drivers/media/i2c/imx412.c F: drivers/media/i2c/imx412.c

View file

@ -35,7 +35,7 @@ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -3568,6 +3568,15 @@ S: Maintained @@ -3569,6 +3569,15 @@ S: Maintained
F: drivers/media/platform/bcm2835/ F: drivers/media/platform/bcm2835/
F: Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml F: Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml

View file

@ -132,7 +132,7 @@ Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
+... +...
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -17543,6 +17543,7 @@ M: Raspberry Pi Kernel Maintenance <kern @@ -17544,6 +17544,7 @@ M: Raspberry Pi Kernel Maintenance <kern
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git

View file

@ -132,7 +132,7 @@ Signed-off-by: Lee Jackson <info@arducam.com>
+... +...
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -17547,6 +17547,14 @@ F: Documentation/devicetree/bindings/med @@ -17548,6 +17548,14 @@ F: Documentation/devicetree/bindings/med
F: Documentation/devicetree/bindings/media/i2c/imx477.yaml F: Documentation/devicetree/bindings/media/i2c/imx477.yaml
F: drivers/media/i2c/imx477.c F: drivers/media/i2c/imx477.c

View file

@ -26,7 +26,7 @@ Signed-off-by: Maxime Ripard <maxime@cerno.tech>
--- a/drivers/gpu/drm/drm_edid.c --- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c
@@ -5742,13 +5742,13 @@ static const u32 hdmi_colorimetry_val[] @@ -5743,13 +5743,13 @@ static const u32 hdmi_colorimetry_val[]
#undef ACE #undef ACE
/** /**
@ -43,7 +43,7 @@ Signed-off-by: Maxime Ripard <maxime@cerno.tech>
const struct drm_connector_state *conn_state) const struct drm_connector_state *conn_state)
{ {
u32 colorimetry_val; u32 colorimetry_val;
@@ -5767,7 +5767,7 @@ drm_hdmi_avi_infoframe_colorspace(struct @@ -5768,7 +5768,7 @@ drm_hdmi_avi_infoframe_colorspace(struct
frame->extended_colorimetry = (colorimetry_val >> 2) & frame->extended_colorimetry = (colorimetry_val >> 2) &
EXTENDED_COLORIMETRY_MASK; EXTENDED_COLORIMETRY_MASK;
} }

View file

@ -63,7 +63,7 @@ Link: https://patchwork.freedesktop.org/patch/msgid/20220227124713.39766-6-noral
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -5980,6 +5980,14 @@ T: git git://anongit.freedesktop.org/drm @@ -5981,6 +5981,14 @@ T: git git://anongit.freedesktop.org/drm
F: Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt F: Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
F: drivers/gpu/drm/tiny/mi0283qt.c F: drivers/gpu/drm/tiny/mi0283qt.c

View file

@ -1,46 +0,0 @@
From d61615c366a489646a1bfe5b33455f916762d5f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Wed, 8 Feb 2023 10:16:37 +0100
Subject: [PATCH] net: bgmac: fix BCM5358 support by setting correct flags
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Code blocks handling BCMA_CHIP_ID_BCM5357 and BCMA_CHIP_ID_BCM53572 were
incorrectly unified. Chip package values are not unique and cannot be
checked independently. They are meaningful only in a context of a given
chip.
Packages BCM5358 and BCM47188 share the same value but then belong to
different chips. Code unification resulted in treating BCM5358 as
BCM47188 and broke its initialization.
Link: https://github.com/openwrt/openwrt/issues/8278
Fixes: cb1b0f90acfe ("net: ethernet: bgmac: unify code of the same family")
Cc: Jon Mason <jdmason@kudzu.us>
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Link: https://lore.kernel.org/r/20230208091637.16291-1-zajec5@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bgmac-bcma.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
@@ -240,12 +240,12 @@ static int bgmac_probe(struct bcma_devic
bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
- if (ci->pkg == BCMA_PKG_ID_BCM47188 ||
- ci->pkg == BCMA_PKG_ID_BCM47186) {
+ if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM47186) ||
+ (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188)) {
bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
}
- if (ci->pkg == BCMA_PKG_ID_BCM5358)
+ if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM5358)
bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII;
break;
case BCMA_CHIP_ID_BCM53573:

View file

@ -20,7 +20,7 @@ Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -3900,6 +3900,7 @@ L: linux-mtd@lists.infradead.org @@ -3901,6 +3901,7 @@ L: linux-mtd@lists.infradead.org
L: bcm-kernel-feedback-list@broadcom.com L: bcm-kernel-feedback-list@broadcom.com
S: Maintained S: Maintained
F: drivers/mtd/nand/raw/brcmnand/ F: drivers/mtd/nand/raw/brcmnand/

View file

@ -95,7 +95,7 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+ }; + };
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -3572,6 +3572,13 @@ F: Documentation/devicetree/bindings/net @@ -3573,6 +3573,13 @@ F: Documentation/devicetree/bindings/net
F: drivers/net/ethernet/broadcom/bcm4908_enet.* F: drivers/net/ethernet/broadcom/bcm4908_enet.*
F: drivers/net/ethernet/broadcom/unimac.h F: drivers/net/ethernet/broadcom/unimac.h

View file

@ -23,7 +23,7 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
--- a/MAINTAINERS --- a/MAINTAINERS
+++ b/MAINTAINERS +++ b/MAINTAINERS
@@ -3578,6 +3578,7 @@ M: bcm-kernel-feedback-list@broadcom.com @@ -3579,6 +3579,7 @@ M: bcm-kernel-feedback-list@broadcom.com
L: linux-gpio@vger.kernel.org L: linux-gpio@vger.kernel.org
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/pinctrl/brcm,bcm4908-pinctrl.yaml F: Documentation/devicetree/bindings/pinctrl/brcm,bcm4908-pinctrl.yaml

View file

@ -11,8 +11,7 @@ BOARDNAME:=Broadcom BCM63xx
SUBTARGETS:=generic smp SUBTARGETS:=generic smp
FEATURES:=squashfs usb atm pci pcmcia usbgadget FEATURES:=squashfs usb atm pci pcmcia usbgadget
KERNEL_PATCHVER:=5.10 KERNEL_PATCHVER:=5.15
KERNEL_TESTING_PATCHVER:=5.15
define Target/Description define Target/Description
Build firmware images for Broadcom based xDSL/routers Build firmware images for Broadcom based xDSL/routers

View file

@ -1,228 +0,0 @@
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_MMAP_RND_BITS_MAX=15
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_BCM6345_EXT_IRQ=y
CONFIG_BCM6345_PERIPH_IRQ=y
CONFIG_BCM63XX=y
CONFIG_BCM63XX_CPU_3368=y
CONFIG_BCM63XX_CPU_6318=y
CONFIG_BCM63XX_CPU_63268=y
CONFIG_BCM63XX_CPU_6328=y
CONFIG_BCM63XX_CPU_6338=y
CONFIG_BCM63XX_CPU_6345=y
CONFIG_BCM63XX_CPU_6348=y
CONFIG_BCM63XX_CPU_6358=y
CONFIG_BCM63XX_CPU_6362=y
CONFIG_BCM63XX_CPU_6368=y
CONFIG_BCM63XX_EHCI=y
CONFIG_BCM63XX_ENET=y
CONFIG_BCM63XX_OHCI=y
CONFIG_BCM63XX_PHY=y
CONFIG_BCM63XX_WDT=y
CONFIG_BCMA=y
CONFIG_BCMA_BLOCKIO=y
# CONFIG_BCMA_DEBUG is not set
# CONFIG_BCMA_DRIVER_GMAC_CMN is not set
# CONFIG_BCMA_DRIVER_MIPS is not set
CONFIG_BCMA_DRIVER_PCI=y
# CONFIG_BCMA_DRIVER_PCI_HOSTMODE is not set
CONFIG_BCMA_HOST_PCI=y
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
# CONFIG_BCMA_HOST_SOC is not set
CONFIG_BCM_NET_PHYLIB=y
CONFIG_BLK_MQ_PCI=y
CONFIG_BOARD_BCM63XX_DT=y
CONFIG_BOARD_BCM963XX=y
CONFIG_BOARD_LIVEBOX=y
CONFIG_CEVT_R4K=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_CPU_BIG_ENDIAN=y
CONFIG_CPU_BMIPS=y
CONFIG_CPU_BMIPS32_3300=y
CONFIG_CPU_BMIPS4350=y
CONFIG_CPU_GENERIC_DUMP_TLB=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_MIPS32=y
CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y
CONFIG_CPU_NO_EFFICIENT_FFS=y
CONFIG_CPU_R4K_CACHE_TLB=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_CPUFREQ=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_CRASH_CORE=y
CONFIG_CRYPTO_BLAKE2S=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2
CONFIG_CRYPTO_RNG2=y
CONFIG_CSRC_R4K=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DTC=y
CONFIG_EARLY_PRINTK=y
CONFIG_FIXED_PHY=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_LIB_ASHLDI3=y
CONFIG_GENERIC_LIB_ASHRDI3=y
CONFIG_GENERIC_LIB_CMPDI2=y
CONFIG_GENERIC_LIB_LSHRDI3=y
CONFIG_GENERIC_LIB_UCMPDI2=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_PINCTRL_GROUPS=y
CONFIG_GENERIC_PINMUX_FUNCTIONS=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GPIO_BCM63XX=y
CONFIG_GPIO_GENERIC=y
CONFIG_HANDLE_DOMAIN_IRQ=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_BCM2835=y
CONFIG_HZ_PERIODIC=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_MIPS_CPU=y
CONFIG_IRQ_WORK=y
CONFIG_KEXEC=y
CONFIG_KEXEC_CORE=y
# CONFIG_LEDS_BCM63138 is not set
CONFIG_LEDS_BCM6328=y
CONFIG_LEDS_BCM6358=y
CONFIG_LEDS_GPIO=y
CONFIG_LIBFDT=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MEMFD_CREATE=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
CONFIG_MIPS=y
CONFIG_MIPS_ASID_BITS=8
CONFIG_MIPS_ASID_SHIFT=0
CONFIG_MIPS_CBPF_JIT=y
CONFIG_MIPS_CLOCK_VSYSCALL=y
# CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set
# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set
CONFIG_MIPS_CMDLINE_FROM_DTB=y
# CONFIG_MIPS_ELF_APPENDED_DTB is not set
CONFIG_MIPS_EXTERNAL_TIMER=y
CONFIG_MIPS_L1_CACHE_SHIFT=4
CONFIG_MIPS_L1_CACHE_SHIFT_4=y
CONFIG_MIPS_LD_CAN_LINK_VDSO=y
# CONFIG_MIPS_NO_APPENDED_DTB is not set
CONFIG_MIPS_RAW_APPENDED_DTB=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MTD_BCM63XX_PARTS=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_BE_BYTE_SWAP=y
# CONFIG_MTD_CFI_GEOMETRY is not set
# CONFIG_MTD_CFI_NOSWAP is not set
CONFIG_MTD_CFI_STAA=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_PARSER_IMAGETAG=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_SPI_NOR=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
CONFIG_NVMEM=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OF_NET=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DRIVERS_LEGACY=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_PHYLIB=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_BCM6318=y
CONFIG_PINCTRL_BCM63268=y
CONFIG_PINCTRL_BCM6328=y
CONFIG_PINCTRL_BCM6348=y
CONFIG_PINCTRL_BCM6358=y
CONFIG_PINCTRL_BCM6362=y
CONFIG_PINCTRL_BCM6368=y
CONFIG_PINCTRL_BCM63XX=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_REGMAP=y
CONFIG_REGMAP_MMIO=y
CONFIG_RELAY=y
CONFIG_RTL8366_SMI=y
CONFIG_RTL8367_PHY=y
# CONFIG_SERIAL_8250 is not set
CONFIG_SERIAL_BCM63XX=y
CONFIG_SERIAL_BCM63XX_CONSOLE=y
CONFIG_SPI=y
CONFIG_SPI_BCM63XX=y
CONFIG_SPI_BCM63XX_HSSPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
CONFIG_SRCU=y
CONFIG_SSB=y
CONFIG_SSB_B43_PCI_BRIDGE=y
CONFIG_SSB_BLOCKIO=y
# CONFIG_SSB_DRIVER_MIPS is not set
CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_PCIHOST=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_SPROM=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_SWCONFIG=y
CONFIG_SWCONFIG_B53=y
CONFIG_SWCONFIG_B53_MMAP_DRIVER=y
CONFIG_SWCONFIG_B53_PHY_DRIVER=y
CONFIG_SWCONFIG_B53_PHY_FIXUP=y
CONFIG_SWCONFIG_B53_SPI_DRIVER=y
CONFIG_SWPHY=y
CONFIG_SYNC_R4K=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_SYS_HAS_CPU_BMIPS=y
CONFIG_SYS_HAS_CPU_BMIPS32_3300=y
CONFIG_SYS_HAS_CPU_BMIPS4350=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y
CONFIG_SYS_SUPPORTS_SMP=y
CONFIG_TARGET_ISA_REV=0
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TINY_SRCU=y
CONFIG_USB_SUPPORT=y
CONFIG_USE_OF=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_WEAK_ORDERING=y

View file

@ -8,8 +8,7 @@ include $(INCLUDE_DIR)/image.mk
KERNEL_LOADADDR = 0x80010000 # RAM start + 64K KERNEL_LOADADDR = 0x80010000 # RAM start + 64K
LOADER_ENTRY = 0x80a00000 # RAM start + 10M, for relocate LOADER_ENTRY = 0x80a00000 # RAM start + 10M, for relocate
RAMSIZE = 0x02000000 # 32MB LZMA_TEXT_START = 0x81800000 # RAM start + 24M
LZMA_TEXT_START = 0x81800000 # 32MB - 8MB
RELOCATE_MAKEOPTS= \ RELOCATE_MAKEOPTS= \
CACHELINE_SIZE=16 \ CACHELINE_SIZE=16 \
@ -37,7 +36,6 @@ define Build/loader-lzma
KDIR=$(KDIR) \ KDIR=$(KDIR) \
LOADER_ADDR=$(if $(DEVICE_LOADADDR),$(DEVICE_LOADADDR),$(LOADER_ENTRY)) \ LOADER_ADDR=$(if $(DEVICE_LOADADDR),$(DEVICE_LOADADDR),$(LOADER_ENTRY)) \
KERNEL_ADDR=$(KERNEL_LOADADDR) \ KERNEL_ADDR=$(KERNEL_LOADADDR) \
RAMSIZE=$(RAMSIZE) \
LZMA_TEXT_START=$(LZMA_TEXT_START) \ LZMA_TEXT_START=$(LZMA_TEXT_START) \
CHIP_ID=$(CHIP_ID) \ CHIP_ID=$(CHIP_ID) \
PKG_BUILD_DIR="$@.src" \ PKG_BUILD_DIR="$@.src" \

View file

@ -1,55 +0,0 @@
From 9cbfea02c1dbee0afb9128f065e6e793672b9ff7 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:02 +0800
Subject: [PATCH 1/7] bcm63xx_enet: batch process rx path
Use netif_receive_skb_list to batch process rx skb.
Tested on BCM6328 320 MHz using iperf3 -M 512, increasing performance
by 12.5%.
Before:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-30.00 sec 120 MBytes 33.7 Mbits/sec 277 sender
[ 4] 0.00-30.00 sec 120 MBytes 33.5 Mbits/sec receiver
After:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-30.00 sec 136 MBytes 37.9 Mbits/sec 203 sender
[ 4] 0.00-30.00 sec 135 MBytes 37.7 Mbits/sec receiver
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -297,10 +297,12 @@ static void bcm_enet_refill_rx_timer(str
static int bcm_enet_receive_queue(struct net_device *dev, int budget)
{
struct bcm_enet_priv *priv;
+ struct list_head rx_list;
struct device *kdev;
int processed;
priv = netdev_priv(dev);
+ INIT_LIST_HEAD(&rx_list);
kdev = &priv->pdev->dev;
processed = 0;
@@ -391,10 +393,12 @@ static int bcm_enet_receive_queue(struct
skb->protocol = eth_type_trans(skb, dev);
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
- netif_receive_skb(skb);
+ list_add_tail(&skb->list, &rx_list);
} while (--budget > 0);
+ netif_receive_skb_list(&rx_list);
+
if (processed || !priv->rx_desc_count) {
bcm_enet_refill_rx(dev);

View file

@ -1,68 +0,0 @@
From 4c59b0f5543db80abbbe9efdd9b25e7899501db5 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:03 +0800
Subject: [PATCH 2/7] bcm63xx_enet: add BQL support
Add Byte Queue Limits support to reduce/remove bufferbloat in
bcm63xx_enet.
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -417,9 +417,11 @@ static int bcm_enet_receive_queue(struct
static int bcm_enet_tx_reclaim(struct net_device *dev, int force)
{
struct bcm_enet_priv *priv;
+ unsigned int bytes;
int released;
priv = netdev_priv(dev);
+ bytes = 0;
released = 0;
while (priv->tx_desc_count < priv->tx_ring_size) {
@@ -456,10 +458,13 @@ static int bcm_enet_tx_reclaim(struct ne
if (desc->len_stat & DMADESC_UNDER_MASK)
dev->stats.tx_errors++;
+ bytes += skb->len;
dev_kfree_skb(skb);
released++;
}
+ netdev_completed_queue(dev, released, bytes);
+
if (netif_queue_stopped(dev) && released)
netif_wake_queue(dev);
@@ -626,6 +631,8 @@ bcm_enet_start_xmit(struct sk_buff *skb,
desc->len_stat = len_stat;
wmb();
+ netdev_sent_queue(dev, skb->len);
+
/* kick tx dma */
enet_dmac_writel(priv, priv->dma_chan_en_mask,
ENETDMAC_CHANCFG, priv->tx_chan);
@@ -1169,6 +1176,7 @@ static int bcm_enet_stop(struct net_devi
kdev = &priv->pdev->dev;
netif_stop_queue(dev);
+ netdev_reset_queue(dev);
napi_disable(&priv->napi);
if (priv->has_phy)
phy_stop(dev->phydev);
@@ -2338,6 +2346,7 @@ static int bcm_enetsw_stop(struct net_de
del_timer_sync(&priv->swphy_poll);
netif_stop_queue(dev);
+ netdev_reset_queue(dev);
napi_disable(&priv->napi);
del_timer_sync(&priv->rx_timeout);

View file

@ -1,26 +0,0 @@
From 375281d3a6dcabaa98f489ee412aedca6d99dffb Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:04 +0800
Subject: [PATCH 3/7] bcm63xx_enet: add xmit_more support
Support bulking hardware TX queue by using netdev_xmit_more().
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -634,7 +634,8 @@ bcm_enet_start_xmit(struct sk_buff *skb,
netdev_sent_queue(dev, skb->len);
/* kick tx dma */
- enet_dmac_writel(priv, priv->dma_chan_en_mask,
+ if (!netdev_xmit_more() || !priv->tx_desc_count)
+ enet_dmac_writel(priv, priv->dma_chan_en_mask,
ENETDMAC_CHANCFG, priv->tx_chan);
/* stop queue if no more desc available */

View file

@ -1,45 +0,0 @@
From c4a207865e7ea310dc146ff4aa1b0aa0c78d3fe1 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:05 +0800
Subject: [PATCH 4/7] bcm63xx_enet: alloc rx skb with NET_IP_ALIGN
Use netdev_alloc_skb_ip_align on newer SoCs with integrated switch
(enetsw) when refilling RX. Increases packet processing performance
by 30% (with netif_receive_skb_list).
Non-enetsw SoCs cannot function with the extra pad so continue to use
the regular netdev_alloc_skb.
Tested on BCM6328 320 MHz and iperf3 -M 512 to measure packet/sec
performance.
Before:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-30.00 sec 120 MBytes 33.7 Mbits/sec 277 sender
[ 4] 0.00-30.00 sec 120 MBytes 33.5 Mbits/sec receiver
After (+netif_receive_skb_list):
[ 4] 0.00-30.00 sec 155 MBytes 43.3 Mbits/sec 354 sender
[ 4] 0.00-30.00 sec 154 MBytes 43.1 Mbits/sec receiver
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -237,7 +237,10 @@ static int bcm_enet_refill_rx(struct net
desc = &priv->rx_desc_cpu[desc_idx];
if (!priv->rx_skb[desc_idx]) {
- skb = netdev_alloc_skb(dev, priv->rx_skb_size);
+ if (priv->enet_is_sw)
+ skb = netdev_alloc_skb_ip_align(dev, priv->rx_skb_size);
+ else
+ skb = netdev_alloc_skb(dev, priv->rx_skb_size);
if (!skb)
break;
priv->rx_skb[desc_idx] = skb;

View file

@ -1,142 +0,0 @@
From 3d0b72654b0c8304424503e7560ee8635dd56340 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:06 +0800
Subject: [PATCH 5/7] bcm63xx_enet: consolidate rx SKB ring cleanup code
The rx SKB ring use the same code for cleanup at various points.
Combine them into a function to reduce lines of code.
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 72 ++++++--------------
1 file changed, 22 insertions(+), 50 deletions(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -860,6 +860,24 @@ static void bcm_enet_adjust_link(struct
priv->pause_tx ? "tx" : "off");
}
+static void bcm_enet_free_rx_skb_ring(struct device *kdev, struct bcm_enet_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->rx_ring_size; i++) {
+ struct bcm_enet_desc *desc;
+
+ if (!priv->rx_skb[i])
+ continue;
+
+ desc = &priv->rx_desc_cpu[i];
+ dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
+ DMA_FROM_DEVICE);
+ kfree_skb(priv->rx_skb[i]);
+ }
+ kfree(priv->rx_skb);
+}
+
/*
* open callback, allocate dma rings & buffers and start rx operation
*/
@@ -1084,18 +1102,7 @@ static int bcm_enet_open(struct net_devi
return 0;
out:
- for (i = 0; i < priv->rx_ring_size; i++) {
- struct bcm_enet_desc *desc;
-
- if (!priv->rx_skb[i])
- continue;
-
- desc = &priv->rx_desc_cpu[i];
- dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
- DMA_FROM_DEVICE);
- kfree_skb(priv->rx_skb[i]);
- }
- kfree(priv->rx_skb);
+ bcm_enet_free_rx_skb_ring(kdev, priv);
out_free_tx_skb:
kfree(priv->tx_skb);
@@ -1174,7 +1181,6 @@ static int bcm_enet_stop(struct net_devi
{
struct bcm_enet_priv *priv;
struct device *kdev;
- int i;
priv = netdev_priv(dev);
kdev = &priv->pdev->dev;
@@ -1203,20 +1209,9 @@ static int bcm_enet_stop(struct net_devi
bcm_enet_tx_reclaim(dev, 1);
/* free the rx skb ring */
- for (i = 0; i < priv->rx_ring_size; i++) {
- struct bcm_enet_desc *desc;
-
- if (!priv->rx_skb[i])
- continue;
-
- desc = &priv->rx_desc_cpu[i];
- dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
- DMA_FROM_DEVICE);
- kfree_skb(priv->rx_skb[i]);
- }
+ bcm_enet_free_rx_skb_ring(kdev, priv);
/* free remaining allocated memory */
- kfree(priv->rx_skb);
kfree(priv->tx_skb);
dma_free_coherent(kdev, priv->rx_desc_alloc_size,
priv->rx_desc_cpu, priv->rx_desc_dma);
@@ -2303,18 +2298,7 @@ static int bcm_enetsw_open(struct net_de
return 0;
out:
- for (i = 0; i < priv->rx_ring_size; i++) {
- struct bcm_enet_desc *desc;
-
- if (!priv->rx_skb[i])
- continue;
-
- desc = &priv->rx_desc_cpu[i];
- dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
- DMA_FROM_DEVICE);
- kfree_skb(priv->rx_skb[i]);
- }
- kfree(priv->rx_skb);
+ bcm_enet_free_rx_skb_ring(kdev, priv);
out_free_tx_skb:
kfree(priv->tx_skb);
@@ -2343,7 +2327,6 @@ static int bcm_enetsw_stop(struct net_de
{
struct bcm_enet_priv *priv;
struct device *kdev;
- int i;
priv = netdev_priv(dev);
kdev = &priv->pdev->dev;
@@ -2366,20 +2349,9 @@ static int bcm_enetsw_stop(struct net_de
bcm_enet_tx_reclaim(dev, 1);
/* free the rx skb ring */
- for (i = 0; i < priv->rx_ring_size; i++) {
- struct bcm_enet_desc *desc;
-
- if (!priv->rx_skb[i])
- continue;
-
- desc = &priv->rx_desc_cpu[i];
- dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
- DMA_FROM_DEVICE);
- kfree_skb(priv->rx_skb[i]);
- }
+ bcm_enet_free_rx_skb_ring(kdev, priv);
/* free remaining allocated memory */
- kfree(priv->rx_skb);
kfree(priv->tx_skb);
dma_free_coherent(kdev, priv->rx_desc_alloc_size,
priv->rx_desc_cpu, priv->rx_desc_dma);

View file

@ -1,347 +0,0 @@
From d27de0ef5ef995df2cc5f5c006c0efcf0a62b6af Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:07 +0800
Subject: [PATCH 6/7] bcm63xx_enet: convert to build_skb
We can increase the efficiency of rx path by using buffers to receive
packets then build SKBs around them just before passing into the network
stack. In contrast, preallocating SKBs too early reduces CPU cache
efficiency.
Check if we're in NAPI context when refilling RX. Normally we're almost
always running in NAPI context. Dispatch to napi_alloc_frag directly
instead of relying on netdev_alloc_frag which does the same but
with the overhead of local_bh_disable/enable.
Tested on BCM6328 320 MHz and iperf3 -M 512 to measure packet/sec
performance. Included netif_receive_skb_list and NET_IP_ALIGN
optimizations.
Before:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 49.9 MBytes 41.9 Mbits/sec 197 sender
[ 4] 0.00-10.00 sec 49.3 MBytes 41.3 Mbits/sec receiver
After:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-30.00 sec 171 MBytes 47.8 Mbits/sec 272 sender
[ 4] 0.00-30.00 sec 170 MBytes 47.6 Mbits/sec receiver
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 111 ++++++++++---------
drivers/net/ethernet/broadcom/bcm63xx_enet.h | 14 ++-
2 files changed, 71 insertions(+), 54 deletions(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -220,7 +220,7 @@ static void bcm_enet_mdio_write_mii(stru
/*
* refill rx queue
*/
-static int bcm_enet_refill_rx(struct net_device *dev)
+static int bcm_enet_refill_rx(struct net_device *dev, bool napi_mode)
{
struct bcm_enet_priv *priv;
@@ -228,29 +228,29 @@ static int bcm_enet_refill_rx(struct net
while (priv->rx_desc_count < priv->rx_ring_size) {
struct bcm_enet_desc *desc;
- struct sk_buff *skb;
- dma_addr_t p;
int desc_idx;
u32 len_stat;
desc_idx = priv->rx_dirty_desc;
desc = &priv->rx_desc_cpu[desc_idx];
- if (!priv->rx_skb[desc_idx]) {
- if (priv->enet_is_sw)
- skb = netdev_alloc_skb_ip_align(dev, priv->rx_skb_size);
+ if (!priv->rx_buf[desc_idx]) {
+ void *buf;
+
+ if (likely(napi_mode))
+ buf = napi_alloc_frag(priv->rx_frag_size);
else
- skb = netdev_alloc_skb(dev, priv->rx_skb_size);
- if (!skb)
+ buf = netdev_alloc_frag(priv->rx_frag_size);
+ if (unlikely(!buf))
break;
- priv->rx_skb[desc_idx] = skb;
- p = dma_map_single(&priv->pdev->dev, skb->data,
- priv->rx_skb_size,
- DMA_FROM_DEVICE);
- desc->address = p;
+ priv->rx_buf[desc_idx] = buf;
+ desc->address = dma_map_single(&priv->pdev->dev,
+ buf + priv->rx_buf_offset,
+ priv->rx_buf_size,
+ DMA_FROM_DEVICE);
}
- len_stat = priv->rx_skb_size << DMADESC_LENGTH_SHIFT;
+ len_stat = priv->rx_buf_size << DMADESC_LENGTH_SHIFT;
len_stat |= DMADESC_OWNER_MASK;
if (priv->rx_dirty_desc == priv->rx_ring_size - 1) {
len_stat |= (DMADESC_WRAP_MASK >> priv->dma_desc_shift);
@@ -290,7 +290,7 @@ static void bcm_enet_refill_rx_timer(str
struct net_device *dev = priv->net_dev;
spin_lock(&priv->rx_lock);
- bcm_enet_refill_rx(dev);
+ bcm_enet_refill_rx(dev, false);
spin_unlock(&priv->rx_lock);
}
@@ -320,6 +320,7 @@ static int bcm_enet_receive_queue(struct
int desc_idx;
u32 len_stat;
unsigned int len;
+ void *buf;
desc_idx = priv->rx_curr_desc;
desc = &priv->rx_desc_cpu[desc_idx];
@@ -365,16 +366,14 @@ static int bcm_enet_receive_queue(struct
}
/* valid packet */
- skb = priv->rx_skb[desc_idx];
+ buf = priv->rx_buf[desc_idx];
len = (len_stat & DMADESC_LENGTH_MASK) >> DMADESC_LENGTH_SHIFT;
/* don't include FCS */
len -= 4;
if (len < copybreak) {
- struct sk_buff *nskb;
-
- nskb = napi_alloc_skb(&priv->napi, len);
- if (!nskb) {
+ skb = napi_alloc_skb(&priv->napi, len);
+ if (unlikely(!skb)) {
/* forget packet, just rearm desc */
dev->stats.rx_dropped++;
continue;
@@ -382,14 +381,21 @@ static int bcm_enet_receive_queue(struct
dma_sync_single_for_cpu(kdev, desc->address,
len, DMA_FROM_DEVICE);
- memcpy(nskb->data, skb->data, len);
+ memcpy(skb->data, buf + priv->rx_buf_offset, len);
dma_sync_single_for_device(kdev, desc->address,
len, DMA_FROM_DEVICE);
- skb = nskb;
} else {
- dma_unmap_single(&priv->pdev->dev, desc->address,
- priv->rx_skb_size, DMA_FROM_DEVICE);
- priv->rx_skb[desc_idx] = NULL;
+ dma_unmap_single(kdev, desc->address,
+ priv->rx_buf_size, DMA_FROM_DEVICE);
+ priv->rx_buf[desc_idx] = NULL;
+
+ skb = build_skb(buf, priv->rx_frag_size);
+ if (unlikely(!skb)) {
+ skb_free_frag(buf);
+ dev->stats.rx_dropped++;
+ continue;
+ }
+ skb_reserve(skb, priv->rx_buf_offset);
}
skb_put(skb, len);
@@ -403,7 +409,7 @@ static int bcm_enet_receive_queue(struct
netif_receive_skb_list(&rx_list);
if (processed || !priv->rx_desc_count) {
- bcm_enet_refill_rx(dev);
+ bcm_enet_refill_rx(dev, true);
/* kick rx dma */
enet_dmac_writel(priv, priv->dma_chan_en_mask,
@@ -860,22 +866,22 @@ static void bcm_enet_adjust_link(struct
priv->pause_tx ? "tx" : "off");
}
-static void bcm_enet_free_rx_skb_ring(struct device *kdev, struct bcm_enet_priv *priv)
+static void bcm_enet_free_rx_buf_ring(struct device *kdev, struct bcm_enet_priv *priv)
{
int i;
for (i = 0; i < priv->rx_ring_size; i++) {
struct bcm_enet_desc *desc;
- if (!priv->rx_skb[i])
+ if (!priv->rx_buf[i])
continue;
desc = &priv->rx_desc_cpu[i];
- dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
+ dma_unmap_single(kdev, desc->address, priv->rx_buf_size,
DMA_FROM_DEVICE);
- kfree_skb(priv->rx_skb[i]);
+ skb_free_frag(priv->rx_buf[i]);
}
- kfree(priv->rx_skb);
+ kfree(priv->rx_buf);
}
/*
@@ -987,10 +993,10 @@ static int bcm_enet_open(struct net_devi
priv->tx_curr_desc = 0;
spin_lock_init(&priv->tx_lock);
- /* init & fill rx ring with skbs */
- priv->rx_skb = kcalloc(priv->rx_ring_size, sizeof(struct sk_buff *),
+ /* init & fill rx ring with buffers */
+ priv->rx_buf = kcalloc(priv->rx_ring_size, sizeof(void *),
GFP_KERNEL);
- if (!priv->rx_skb) {
+ if (!priv->rx_buf) {
ret = -ENOMEM;
goto out_free_tx_skb;
}
@@ -1007,8 +1013,8 @@ static int bcm_enet_open(struct net_devi
enet_dmac_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
ENETDMAC_BUFALLOC, priv->rx_chan);
- if (bcm_enet_refill_rx(dev)) {
- dev_err(kdev, "cannot allocate rx skb queue\n");
+ if (bcm_enet_refill_rx(dev, false)) {
+ dev_err(kdev, "cannot allocate rx buffer queue\n");
ret = -ENOMEM;
goto out;
}
@@ -1102,7 +1108,7 @@ static int bcm_enet_open(struct net_devi
return 0;
out:
- bcm_enet_free_rx_skb_ring(kdev, priv);
+ bcm_enet_free_rx_buf_ring(kdev, priv);
out_free_tx_skb:
kfree(priv->tx_skb);
@@ -1208,8 +1214,8 @@ static int bcm_enet_stop(struct net_devi
/* force reclaim of all tx buffers */
bcm_enet_tx_reclaim(dev, 1);
- /* free the rx skb ring */
- bcm_enet_free_rx_skb_ring(kdev, priv);
+ /* free the rx buffer ring */
+ bcm_enet_free_rx_buf_ring(kdev, priv);
/* free remaining allocated memory */
kfree(priv->tx_skb);
@@ -1633,9 +1639,12 @@ static int bcm_enet_change_mtu(struct ne
* align rx buffer size to dma burst len, account FCS since
* it's appended
*/
- priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
+ priv->rx_buf_size = ALIGN(actual_mtu + ETH_FCS_LEN,
priv->dma_maxburst * 4);
+ priv->rx_frag_size = SKB_DATA_ALIGN(priv->rx_buf_offset + priv->rx_buf_size) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
dev->mtu = new_mtu;
return 0;
}
@@ -1720,6 +1729,7 @@ static int bcm_enet_probe(struct platfor
priv->enet_is_sw = false;
priv->dma_maxburst = BCMENET_DMA_MAXBURST;
+ priv->rx_buf_offset = NET_SKB_PAD;
ret = bcm_enet_change_mtu(dev, dev->mtu);
if (ret)
@@ -2137,7 +2147,7 @@ static int bcm_enetsw_open(struct net_de
priv->tx_skb = kcalloc(priv->tx_ring_size, sizeof(struct sk_buff *),
GFP_KERNEL);
if (!priv->tx_skb) {
- dev_err(kdev, "cannot allocate rx skb queue\n");
+ dev_err(kdev, "cannot allocate tx skb queue\n");
ret = -ENOMEM;
goto out_free_tx_ring;
}
@@ -2147,11 +2157,11 @@ static int bcm_enetsw_open(struct net_de
priv->tx_curr_desc = 0;
spin_lock_init(&priv->tx_lock);
- /* init & fill rx ring with skbs */
- priv->rx_skb = kcalloc(priv->rx_ring_size, sizeof(struct sk_buff *),
+ /* init & fill rx ring with buffers */
+ priv->rx_buf = kcalloc(priv->rx_ring_size, sizeof(void *),
GFP_KERNEL);
- if (!priv->rx_skb) {
- dev_err(kdev, "cannot allocate rx skb queue\n");
+ if (!priv->rx_buf) {
+ dev_err(kdev, "cannot allocate rx buffer queue\n");
ret = -ENOMEM;
goto out_free_tx_skb;
}
@@ -2198,8 +2208,8 @@ static int bcm_enetsw_open(struct net_de
enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
ENETDMA_BUFALLOC_REG(priv->rx_chan));
- if (bcm_enet_refill_rx(dev)) {
- dev_err(kdev, "cannot allocate rx skb queue\n");
+ if (bcm_enet_refill_rx(dev, false)) {
+ dev_err(kdev, "cannot allocate rx buffer queue\n");
ret = -ENOMEM;
goto out;
}
@@ -2298,7 +2308,7 @@ static int bcm_enetsw_open(struct net_de
return 0;
out:
- bcm_enet_free_rx_skb_ring(kdev, priv);
+ bcm_enet_free_rx_buf_ring(kdev, priv);
out_free_tx_skb:
kfree(priv->tx_skb);
@@ -2348,8 +2358,8 @@ static int bcm_enetsw_stop(struct net_de
/* force reclaim of all tx buffers */
bcm_enet_tx_reclaim(dev, 1);
- /* free the rx skb ring */
- bcm_enet_free_rx_skb_ring(kdev, priv);
+ /* free the rx buffer ring */
+ bcm_enet_free_rx_buf_ring(kdev, priv);
/* free remaining allocated memory */
kfree(priv->tx_skb);
@@ -2648,6 +2658,7 @@ static int bcm_enetsw_probe(struct platf
priv->rx_ring_size = BCMENET_DEF_RX_DESC;
priv->tx_ring_size = BCMENET_DEF_TX_DESC;
priv->dma_maxburst = BCMENETSW_DMA_MAXBURST;
+ priv->rx_buf_offset = NET_SKB_PAD + NET_IP_ALIGN;
pd = dev_get_platdata(&pdev->dev);
if (pd) {
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
@@ -230,11 +230,17 @@ struct bcm_enet_priv {
/* next dirty rx descriptor to refill */
int rx_dirty_desc;
- /* size of allocated rx skbs */
- unsigned int rx_skb_size;
+ /* size of allocated rx buffers */
+ unsigned int rx_buf_size;
- /* list of skb given to hw for rx */
- struct sk_buff **rx_skb;
+ /* allocated rx buffer offset */
+ unsigned int rx_buf_offset;
+
+ /* size of allocated rx frag */
+ unsigned int rx_frag_size;
+
+ /* list of buffer given to hw for rx */
+ void **rx_buf;
/* used when rx skb allocation failed, so we defer rx queue
* refill */

View file

@ -1,40 +0,0 @@
From ae2259eebeacb7753e3043278957b45840123972 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Wed, 6 Jan 2021 22:42:08 +0800
Subject: [PATCH 7/7] bcm63xx_enet: improve rx loop
Use existing rx processed count to track against budget, thereby making
budget decrement operation redundant.
rx_desc_count can be calculated outside the rx loop, making the loop a
bit smaller.
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -339,7 +339,6 @@ static int bcm_enet_receive_queue(struct
priv->rx_curr_desc++;
if (priv->rx_curr_desc == priv->rx_ring_size)
priv->rx_curr_desc = 0;
- priv->rx_desc_count--;
/* if the packet does not have start of packet _and_
* end of packet flag set, then just recycle it */
@@ -404,9 +403,10 @@ static int bcm_enet_receive_queue(struct
dev->stats.rx_bytes += len;
list_add_tail(&skb->list, &rx_list);
- } while (--budget > 0);
+ } while (processed < budget);
netif_receive_skb_list(&rx_list);
+ priv->rx_desc_count -= processed;
if (processed || !priv->rx_desc_count) {
bcm_enet_refill_rx(dev, true);

View file

@ -1,58 +0,0 @@
From 90eda07518ea7e8d1b3e6445eb3633eef9f65218 Mon Sep 17 00:00:00 2001
From: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Date: Mon, 22 Feb 2021 09:15:12 +0800
Subject: [PATCH net] bcm63xx_enet: fix sporadic kernel panic
In ndo_stop functions, netdev_completed_queue() is called during forced
tx reclaim, after netdev_reset_queue(). This may trigger kernel panic if
there is any tx skb left.
This patch moves netdev_reset_queue() to after tx reclaim, so BQL can
complete successfully then reset.
Signed-off-by: Sieng Piaw Liew <liew.s.piaw@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Fixes: 4c59b0f5543d ("bcm63xx_enet: add BQL support")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1192,7 +1192,6 @@ static int bcm_enet_stop(struct net_devi
kdev = &priv->pdev->dev;
netif_stop_queue(dev);
- netdev_reset_queue(dev);
napi_disable(&priv->napi);
if (priv->has_phy)
phy_stop(dev->phydev);
@@ -1231,6 +1230,9 @@ static int bcm_enet_stop(struct net_devi
if (priv->has_phy)
phy_disconnect(dev->phydev);
+ /* reset BQL after forced tx reclaim to not kernel panic */
+ netdev_reset_queue(dev);
+
return 0;
}
@@ -2343,7 +2345,6 @@ static int bcm_enetsw_stop(struct net_de
del_timer_sync(&priv->swphy_poll);
netif_stop_queue(dev);
- netdev_reset_queue(dev);
napi_disable(&priv->napi);
del_timer_sync(&priv->rx_timeout);
@@ -2371,6 +2372,9 @@ static int bcm_enetsw_stop(struct net_de
free_irq(priv->irq_tx, dev);
free_irq(priv->irq_rx, dev);
+ /* reset BQL after forced tx reclaim to not kernel panic */
+ netdev_reset_queue(dev);
+
return 0;
}

View file

@ -1,28 +0,0 @@
From 80a2f983e9f44dbc3e01ae31c62d877846a7f791 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:19 +0100
Subject: [PATCH 01/11] MIPS: BCM63XX: add USB host clock enable delay
Knowledge of the clock setup delay should remain at the clock level (so
it can be clock specific and CPU specific). Add the 100 milliseconds
required clock delay for the USB host clock when it gets enabled.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/clk.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -214,6 +214,11 @@ static void usbh_set(struct clk *clk, in
bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
else if (BCMCPU_IS_6368())
bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
+ else
+ return;
+
+ if (enable)
+ msleep(100);
}
static struct clk clk_usbh = {

View file

@ -1,18 +0,0 @@
bcm63xx: fix booting with Kernel 5.10
This is a workaround to make the target overall bootable. With this more
people should be able to test the Kernel 5.10 and report further issues.
Suggested-by: Daniel González Cabanelas <dgcbueu@gmail.com>
Signed-off-by: Paul Spooren <mail@aparcar.org>
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -323,7 +323,7 @@ static int macronix_nand_init(struct nan
macronix_nand_fix_broken_get_timings(chip);
macronix_nand_onfi_init(chip);
- macronix_nand_block_protection_support(chip);
+ //macronix_nand_block_protection_support(chip);
macronix_nand_deep_power_down_support(chip);
return 0;

View file

@ -1,41 +0,0 @@
From 8e9bf528a122741f0171b89c297b63041116d704 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:20 +0100
Subject: [PATCH 02/11] MIPS: BCM63XX: add USB device clock enable delay to
clock code
This patch adds the required 10 micro seconds delay to the USB device
clock enable operation. Put this where the correct clock knowledege is,
which is in the clock code, and remove this delay from the bcm63xx_udc
gadget driver where it was before.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/clk.c | 5 +++++
drivers/usb/gadget/bcm63xx_udc.c | 1 -
2 files changed, 5 insertions(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -236,6 +236,11 @@ static void usbd_set(struct clk *clk, in
bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
else if (BCMCPU_IS_6368())
bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
+ else
+ return;
+
+ if (enable)
+ udelay(10);
}
static struct clk clk_usbd = {
--- a/drivers/usb/gadget/udc/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -403,7 +403,6 @@ static inline void set_clocks(struct bcm
if (is_enabled) {
clk_enable(udc->usbh_clk);
clk_enable(udc->usbd_clk);
- udelay(10);
} else {
clk_disable(udc->usbd_clk);
clk_disable(udc->usbh_clk);

View file

@ -1,151 +0,0 @@
From ac9b0b574d54be28b300bf99ffe092a2c589484f Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:21 +0100
Subject: [PATCH 03/11] MIPS: BCM63XX: move code touching the USB private
register
This patch moves the code touching the USB private register in the
bcm63xx USB gadget driver to arch/mips/bcm63xx/usb-common.c in
preparation for adding support for OHCI and EHCI host controllers which
will also touch the USB private register.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Makefile | 2 +-
arch/mips/bcm63xx/usb-common.c | 53 ++++++++++++++++++++
.../include/asm/mach-bcm63xx/bcm63xx_usb_priv.h | 9 ++++
drivers/usb/gadget/bcm63xx_udc.c | 27 ++--------
4 files changed, 67 insertions(+), 24 deletions(-)
create mode 100644 arch/mips/bcm63xx/usb-common.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -2,7 +2,7 @@
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
setup.o timer.o dev-enet.o dev-flash.o dev-pcmcia.o \
dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o dev-wdt.o \
- dev-usb-usbd.o
+ dev-usb-usbd.o usb-common.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- /dev/null
+++ b/arch/mips/bcm63xx/usb-common.c
@@ -0,0 +1,53 @@
+/*
+ * Broadcom BCM63xx common USB device configuration code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 Kevin Cernekee <cernekee@gmail.com>
+ * Copyright (C) 2012 Broadcom Corporation
+ *
+ */
+#include <linux/export.h>
+
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_usb_priv.h>
+
+void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device)
+{
+ u32 val;
+
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
+ if (is_device) {
+ val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
+ val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ } else {
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ }
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ if (is_device)
+ val |= USBH_PRIV_SWAP_USBD_MASK;
+ else
+ val &= ~USBH_PRIV_SWAP_USBD_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
+}
+EXPORT_SYMBOL(bcm63xx_usb_priv_select_phy_mode);
+
+void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on)
+{
+ u32 val;
+
+ val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
+ if (is_on)
+ val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ else
+ val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+ bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+}
+EXPORT_SYMBOL(bcm63xx_usb_priv_select_pullup);
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
@@ -0,0 +1,9 @@
+#ifndef BCM63XX_USB_PRIV_H_
+#define BCM63XX_USB_PRIV_H_
+
+#include <linux/types.h>
+
+void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device);
+void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on);
+
+#endif /* BCM63XX_USB_PRIV_H_ */
--- a/drivers/usb/gadget/udc/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -36,6 +36,7 @@
#include <bcm63xx_dev_usb_usbd.h>
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
+#include <bcm63xx_usb_priv.h>
#define DRV_MODULE_NAME "bcm63xx_udc"
@@ -880,22 +881,7 @@ static void bcm63xx_select_phy_mode(stru
bcm_gpio_writel(val, GPIO_PINMUX_OTHR_REG);
}
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
- if (is_device) {
- val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
- val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- } else {
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- }
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
-
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
- if (is_device)
- val |= USBH_PRIV_SWAP_USBD_MASK;
- else
- val &= ~USBH_PRIV_SWAP_USBD_MASK;
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
+ bcm63xx_usb_priv_select_phy_mode(portmask, is_device);
}
/**
@@ -909,14 +895,9 @@ static void bcm63xx_select_phy_mode(stru
*/
static void bcm63xx_select_pullup(struct bcm63xx_udc *udc, bool is_on)
{
- u32 val, portmask = BIT(udc->pd->port_no);
+ u32 portmask = BIT(udc->pd->port_no);
- val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
- if (is_on)
- val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- else
- val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
- bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+ bcm63xx_usb_priv_select_pullup(portmask, is_on);
}
/**

View file

@ -1,169 +0,0 @@
From 28758a9da77954ed323f86123ef448c6a563c037 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:22 +0100
Subject: [PATCH 04/11] MIPS: BCM63XX: add OHCI/EHCI configuration bits to
common USB code
This patch updates the common USB code touching the USB private
registers with the specific bits to properly enable OHCI and EHCI
controllers on BCM63xx SoCs. As a result we now need to protect access
to Read Modify Write sequences using a spinlock because we cannot
guarantee that any of the exposed helper will not be called
concurrently.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/usb-common.c | 97 ++++++++++++++++++++
.../include/asm/mach-bcm63xx/bcm63xx_usb_priv.h | 2 +
2 files changed, 99 insertions(+)
--- a/arch/mips/bcm63xx/usb-common.c
+++ b/arch/mips/bcm63xx/usb-common.c
@@ -5,10 +5,12 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
* Copyright (C) 2012 Kevin Cernekee <cernekee@gmail.com>
* Copyright (C) 2012 Broadcom Corporation
*
*/
+#include <linux/spinlock.h>
#include <linux/export.h>
#include <bcm63xx_cpu.h>
@@ -16,9 +18,14 @@
#include <bcm63xx_io.h>
#include <bcm63xx_usb_priv.h>
+static DEFINE_SPINLOCK(usb_priv_reg_lock);
+
void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device)
{
u32 val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
if (is_device) {
@@ -36,12 +43,17 @@ void bcm63xx_usb_priv_select_phy_mode(u3
else
val &= ~USBH_PRIV_SWAP_USBD_MASK;
bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
+
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
}
EXPORT_SYMBOL(bcm63xx_usb_priv_select_phy_mode);
void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on)
{
u32 val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
if (is_on)
@@ -49,5 +61,90 @@ void bcm63xx_usb_priv_select_pullup(u32
else
val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
}
EXPORT_SYMBOL(bcm63xx_usb_priv_select_pullup);
+
+/* The following array represents the meaning of the DESC/DATA
+ * endian swapping with respect to the CPU configured endianness
+ *
+ * DATA ENDN mmio descriptor
+ * 0 0 BE invalid
+ * 0 1 BE LE
+ * 1 0 BE BE
+ * 1 1 BE invalid
+ *
+ * Since BCM63XX SoCs are configured to be in big-endian mode
+ * we want configuration at line 3.
+ */
+void bcm63xx_usb_priv_ohci_cfg_set(void)
+{
+ u32 reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
+
+ if (BCMCPU_IS_6348())
+ bcm_rset_writel(RSET_OHCI_PRIV, 0, OHCI_PRIV_REG);
+ else if (BCMCPU_IS_6358()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
+ reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
+ reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
+ /*
+ * The magic value comes for the original vendor BSP
+ * and is needed for USB to work. Datasheet does not
+ * help, so the magic value is used as-is.
+ */
+ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
+ USBH_PRIV_TEST_6358_REG);
+
+ } else if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
+ reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG);
+ reg |= USBH_PRIV_SETUP_IOC_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
+ }
+
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
+}
+
+void bcm63xx_usb_priv_ehci_cfg_set(void)
+{
+ u32 reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&usb_priv_reg_lock, flags);
+
+ if (BCMCPU_IS_6358()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
+ reg &= ~USBH_PRIV_SWAP_EHCI_ENDN_MASK;
+ reg |= USBH_PRIV_SWAP_EHCI_DATA_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
+
+ /*
+ * The magic value comes for the original vendor BSP
+ * and is needed for USB to work. Datasheet does not
+ * help, so the magic value is used as-is.
+ */
+ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
+ USBH_PRIV_TEST_6358_REG);
+
+ } else if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ reg &= ~USBH_PRIV_SWAP_EHCI_ENDN_MASK;
+ reg |= USBH_PRIV_SWAP_EHCI_DATA_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG);
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG);
+ reg |= USBH_PRIV_SETUP_IOC_MASK;
+ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
+ }
+
+ spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
+}
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
@@ -5,5 +5,7 @@
void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device);
void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on);
+void bcm63xx_usb_priv_ohci_cfg_set(void);
+void bcm63xx_usb_priv_ehci_cfg_set(void);
#endif /* BCM63XX_USB_PRIV_H_ */

View file

@ -1,62 +0,0 @@
From 94ec618bd1a6b07fafbbfc9bcc54e7f9360ff9a0 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:23 +0100
Subject: [PATCH 05/11] MIPS: BCM63XX: introduce BCM63XX_OHCI configuration
symbol
This configuration symbol can be used by CPUs supporting the on-chip
OHCI controller, and ensures that all relevant OHCI-related
configuration options are correctly selected. So far, OHCI support is
available for the 6328, 6348, 6358 and 6358 SoCs.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Kconfig | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -7,10 +7,17 @@ config BCM63XX_CPU_3368
select SYS_HAS_CPU_BMIPS4350
select HAVE_PCI
+config BCM63XX_OHCI
+ bool
+ select USB_ARCH_HAS_OHCI
+ select USB_OHCI_BIG_ENDIAN_DESC if USB_OHCI_HCD
+ select USB_OHCI_BIG_ENDIAN_MMIO if USB_OHCI_HCD
+
config BCM63XX_CPU_6328
bool "support 6328 CPU"
select SYS_HAS_CPU_BMIPS4350
select HAVE_PCI
+ select BCM63XX_OHCI
config BCM63XX_CPU_6338
bool "support 6338 CPU"
@@ -25,21 +32,25 @@ config BCM63XX_CPU_6348
bool "support 6348 CPU"
select SYS_HAS_CPU_BMIPS32_3300
select HAVE_PCI
+ select BCM63XX_OHCI
config BCM63XX_CPU_6358
bool "support 6358 CPU"
select SYS_HAS_CPU_BMIPS4350
select HAVE_PCI
+ select BCM63XX_OHCI
config BCM63XX_CPU_6362
bool "support 6362 CPU"
select SYS_HAS_CPU_BMIPS4350
select HAVE_PCI
+ select BCM63XX_OHCI
config BCM63XX_CPU_6368
bool "support 6368 CPU"
select SYS_HAS_CPU_BMIPS4350
select HAVE_PCI
+ select BCM63XX_OHCI
endmenu
source "arch/mips/bcm63xx/boards/Kconfig"

View file

@ -1,138 +0,0 @@
From 30d22baef255c99a12c4858ce4ab0d45f0d8c9ae Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:24 +0100
Subject: [PATCH 06/11] MIPS: BCM63XX: add support for the on-chip OHCI
controller
Broadcom BCM63XX SoCs include an on-chip OHCI controller which can be
driven by the ohci-platform generic driver by using specific power
on/off/suspend callback to manage clocks and hardware specific
configuration.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Makefile | 2 +-
arch/mips/bcm63xx/dev-usb-ohci.c | 94 ++++++++++++++++++++
.../asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h | 6 ++
3 files changed, 101 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/bcm63xx/dev-usb-ohci.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -2,7 +2,7 @@
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
setup.o timer.o dev-enet.o dev-flash.o dev-pcmcia.o \
dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o dev-wdt.o \
- dev-usb-usbd.o usb-common.o
+ dev-usb-ohci.o dev-usb-usbd.o usb-common.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- /dev/null
+++ b/arch/mips/bcm63xx/dev-usb-ohci.c
@@ -0,0 +1,94 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2013 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_usb_priv.h>
+#include <bcm63xx_dev_usb_ohci.h>
+
+static struct resource ohci_resources[] = {
+ {
+ .start = -1, /* filled at runtime */
+ .end = -1, /* filled at runtime */
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = -1, /* filled at runtime */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 ohci_dmamask = DMA_BIT_MASK(32);
+
+static struct clk *usb_host_clock;
+
+static int bcm63xx_ohci_power_on(struct platform_device *pdev)
+{
+ usb_host_clock = clk_get(&pdev->dev, "usbh");
+ if (IS_ERR_OR_NULL(usb_host_clock))
+ return -ENODEV;
+
+ clk_prepare_enable(usb_host_clock);
+
+ bcm63xx_usb_priv_ohci_cfg_set();
+
+ return 0;
+}
+
+static void bcm63xx_ohci_power_off(struct platform_device *pdev)
+{
+ if (!IS_ERR_OR_NULL(usb_host_clock)) {
+ clk_disable_unprepare(usb_host_clock);
+ clk_put(usb_host_clock);
+ }
+}
+
+static struct usb_ohci_pdata bcm63xx_ohci_pdata = {
+ .big_endian_desc = 1,
+ .big_endian_mmio = 1,
+ .no_big_frame_no = 1,
+ .num_ports = 1,
+ .power_on = bcm63xx_ohci_power_on,
+ .power_off = bcm63xx_ohci_power_off,
+ .power_suspend = bcm63xx_ohci_power_off,
+};
+
+static struct platform_device bcm63xx_ohci_device = {
+ .name = "ohci-platform",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ohci_resources),
+ .resource = ohci_resources,
+ .dev = {
+ .platform_data = &bcm63xx_ohci_pdata,
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+int __init bcm63xx_ohci_register(void)
+{
+ if (BCMCPU_IS_6345() || BCMCPU_IS_6338())
+ return -ENODEV;
+
+ ohci_resources[0].start = bcm63xx_regset_address(RSET_OHCI0);
+ ohci_resources[0].end = ohci_resources[0].start;
+ ohci_resources[0].end += RSET_OHCI_SIZE - 1;
+ ohci_resources[1].start = bcm63xx_get_irq_number(IRQ_OHCI0);
+
+ return platform_device_register(&bcm63xx_ohci_device);
+}
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
@@ -0,0 +1,6 @@
+#ifndef BCM63XX_DEV_USB_OHCI_H_
+#define BCM63XX_DEV_USB_OHCI_H_
+
+int bcm63xx_ohci_register(void);
+
+#endif /* BCM63XX_DEV_USB_OHCI_H_ */

View file

@ -1,36 +0,0 @@
From 33ef960aed15f9a98a2c51d8d794cd72418e0be4 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:25 +0100
Subject: [PATCH 07/11] MIPS: BCM63XX: register OHCI controller if board
enables it
BCM63XX-based boards can control the registration of the OHCI controller
by setting their has_ohci0 flag to 1. Handle this in the generic
code dealing with board registration and call the actual helper to
register the OHCI controller.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -24,6 +24,7 @@
#include <bcm63xx_dev_hsspi.h>
#include <bcm63xx_dev_pcmcia.h>
#include <bcm63xx_dev_spi.h>
+#include <bcm63xx_dev_usb_ohci.h>
#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
@@ -879,6 +880,9 @@ int __init board_register_devices(void)
if (board.has_usbd)
bcm63xx_usbd_register(&board.usbd);
+ if (board.has_ohci0)
+ bcm63xx_ohci_register();
+
/* Generate MAC address for WLAN and register our SPROM,
* do this after registering enet devices
*/

View file

@ -1,62 +0,0 @@
From 00da1683364e58c6430a4577123d01037f8faddc Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:26 +0100
Subject: [PATCH 08/11] MIPS: BCM63XX: introduce BCM63XX_EHCI configuration
symbol
This configuration symbol can be used by CPUs supporting the on-chip
EHCI controller, and ensures that all relevant EHCI-related
configuration options are selected. So far BCM6328, BCM6358 and BCM6368
have an EHCI controller and do select this symbol. Update
drivers/usb/host/Kconfig with BCM63XX to update direct unmet
dependencies.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Kconfig | 9 +++++++++
drivers/usb/host/Kconfig | 5 +++--
2 files changed, 12 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -13,11 +13,18 @@ config BCM63XX_OHCI
select USB_OHCI_BIG_ENDIAN_DESC if USB_OHCI_HCD
select USB_OHCI_BIG_ENDIAN_MMIO if USB_OHCI_HCD
+config BCM63XX_EHCI
+ bool
+ select USB_ARCH_HAS_EHCI
+ select USB_EHCI_BIG_ENDIAN_DESC if USB_EHCI_HCD
+ select USB_EHCI_BIG_ENDIAN_MMIO if USB_EHCI_HCD
+
config BCM63XX_CPU_6328
bool "support 6328 CPU"
select SYS_HAS_CPU_BMIPS4350
select HAVE_PCI
select BCM63XX_OHCI
+ select BCM63XX_EHCI
config BCM63XX_CPU_6338
bool "support 6338 CPU"
@@ -39,18 +46,21 @@ config BCM63XX_CPU_6358
select SYS_HAS_CPU_BMIPS4350
select HAVE_PCI
select BCM63XX_OHCI
+ select BCM63XX_EHCI
config BCM63XX_CPU_6362
bool "support 6362 CPU"
select SYS_HAS_CPU_BMIPS4350
select HAVE_PCI
select BCM63XX_OHCI
+ select BCM63XX_EHCI
config BCM63XX_CPU_6368
bool "support 6368 CPU"
select SYS_HAS_CPU_BMIPS4350
select HAVE_PCI
select BCM63XX_OHCI
+ select BCM63XX_EHCI
endmenu
source "arch/mips/bcm63xx/boards/Kconfig"

View file

@ -1,136 +0,0 @@
From e38f13bd6408769c0b565bb1079024f496eee121 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:27 +0100
Subject: [PATCH 09/11] MIPS: BCM63XX: add support for the on-chip EHCI
controller
Broadcom BCM63XX SoCs include an on-chip EHCI controller which can be
driven by the generic ehci-platform driver by using specific power
on/off/suspend callbacks to manage clocks and hardware specific
configuration.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/Makefile | 2 +-
arch/mips/bcm63xx/dev-usb-ehci.c | 92 ++++++++++++++++++++
.../asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h | 6 ++
3 files changed, 99 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/bcm63xx/dev-usb-ehci.c
create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -2,7 +2,7 @@
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
setup.o timer.o dev-enet.o dev-flash.o dev-pcmcia.o \
dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o dev-wdt.o \
- dev-usb-ohci.o dev-usb-usbd.o usb-common.o
+ dev-usb-ehci.o dev-usb-ohci.o dev-usb-usbd.o usb-common.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
--- /dev/null
+++ b/arch/mips/bcm63xx/dev-usb-ehci.c
@@ -0,0 +1,92 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2013 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/dma-mapping.h>
+
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_usb_priv.h>
+#include <bcm63xx_dev_usb_ehci.h>
+
+static struct resource ehci_resources[] = {
+ {
+ .start = -1, /* filled at runtime */
+ .end = -1, /* filled at runtime */
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = -1, /* filled at runtime */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 ehci_dmamask = DMA_BIT_MASK(32);
+
+static struct clk *usb_host_clock;
+
+static int bcm63xx_ehci_power_on(struct platform_device *pdev)
+{
+ usb_host_clock = clk_get(&pdev->dev, "usbh");
+ if (IS_ERR_OR_NULL(usb_host_clock))
+ return -ENODEV;
+
+ clk_prepare_enable(usb_host_clock);
+
+ bcm63xx_usb_priv_ehci_cfg_set();
+
+ return 0;
+}
+
+static void bcm63xx_ehci_power_off(struct platform_device *pdev)
+{
+ if (!IS_ERR_OR_NULL(usb_host_clock)) {
+ clk_disable_unprepare(usb_host_clock);
+ clk_put(usb_host_clock);
+ }
+}
+
+static struct usb_ehci_pdata bcm63xx_ehci_pdata = {
+ .big_endian_desc = 1,
+ .big_endian_mmio = 1,
+ .power_on = bcm63xx_ehci_power_on,
+ .power_off = bcm63xx_ehci_power_off,
+ .power_suspend = bcm63xx_ehci_power_off,
+};
+
+static struct platform_device bcm63xx_ehci_device = {
+ .name = "ehci-platform",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ehci_resources),
+ .resource = ehci_resources,
+ .dev = {
+ .platform_data = &bcm63xx_ehci_pdata,
+ .dma_mask = &ehci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+int __init bcm63xx_ehci_register(void)
+{
+ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6358() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
+ return 0;
+
+ ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);
+ ehci_resources[0].end = ehci_resources[0].start;
+ ehci_resources[0].end += RSET_EHCI_SIZE - 1;
+ ehci_resources[1].start = bcm63xx_get_irq_number(IRQ_EHCI0);
+
+ return platform_device_register(&bcm63xx_ehci_device);
+}
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
@@ -0,0 +1,6 @@
+#ifndef BCM63XX_DEV_USB_EHCI_H_
+#define BCM63XX_DEV_USB_EHCI_H_
+
+int bcm63xx_ehci_register(void);
+
+#endif /* BCM63XX_DEV_USB_EHCI_H_ */

View file

@ -1,36 +0,0 @@
From 709ef2034f5ba06da35f89856ad7baf2b7a41287 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:28 +0100
Subject: [PATCH 10/11] MIPS: BCM63XX: register EHCI controller if board
enables it
BCM63XX-based board can control the registration of the EHCI controller
by setting their has_ehci0 flag to 1. Handle this in the generic
code dealing with board registration and call the actual helper to register
the EHCI controller.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -24,6 +24,7 @@
#include <bcm63xx_dev_hsspi.h>
#include <bcm63xx_dev_pcmcia.h>
#include <bcm63xx_dev_spi.h>
+#include <bcm63xx_dev_usb_ehci.h>
#include <bcm63xx_dev_usb_ohci.h>
#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
@@ -880,6 +881,9 @@ int __init board_register_devices(void)
if (board.has_usbd)
bcm63xx_usbd_register(&board.usbd);
+ if (board.has_ehci0)
+ bcm63xx_ehci_register();
+
if (board.has_ohci0)
bcm63xx_ohci_register();

View file

@ -1,24 +0,0 @@
From 111bbd770441ab34f9da5bb1d85767a9b75227b4 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 28 Jan 2013 20:06:30 +0100
Subject: [PATCH 12/12] MIPS: BCM63XX: EHCI controller does not support
overcurrent
This patch sets the spurious_oc flag for the BCM63XX EHCI controller as it
does not support proper overcurrent reporting.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
arch/mips/bcm63xx/dev-usb-ehci.c | 1 +
1 file changed, 1 insertion(+)
--- a/arch/mips/bcm63xx/dev-usb-ehci.c
+++ b/arch/mips/bcm63xx/dev-usb-ehci.c
@@ -61,6 +61,7 @@ static void bcm63xx_ehci_power_off(struc
static struct usb_ehci_pdata bcm63xx_ehci_pdata = {
.big_endian_desc = 1,
.big_endian_mmio = 1,
+ .spurious_oc = 1,
.power_on = bcm63xx_ehci_power_on,
.power_off = bcm63xx_ehci_power_off,
.power_suspend = bcm63xx_ehci_power_off,

View file

@ -1,226 +0,0 @@
From ab2f33e35e35905a76204138143875251f3e1088 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:07:42 +0200
Subject: [PATCH 01/13] pinctrl: add bcm63xx base code
Setup directory and add a helper for bcm63xx pinctrl support.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/Kconfig | 1 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/bcm63xx/Kconfig | 3 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c | 142 ++++++++++++++++++++++++++++++
drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h | 14 +++
7 files changed, 163 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/Kconfig
create mode 100644 drivers/pinctrl/bcm63xx/Makefile
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -377,6 +377,7 @@ config PINCTRL_OCELOT
source "drivers/pinctrl/actions/Kconfig"
source "drivers/pinctrl/aspeed/Kconfig"
source "drivers/pinctrl/bcm/Kconfig"
+source "drivers/pinctrl/bcm63xx/Kconfig"
source "drivers/pinctrl/berlin/Kconfig"
source "drivers/pinctrl/freescale/Kconfig"
source "drivers/pinctrl/intel/Kconfig"
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_PINCTRL_EQUILIBRIUM) += p
obj-y += actions/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
obj-y += bcm/
+obj-y += bcm63xx/
obj-$(CONFIG_PINCTRL_BERLIN) += berlin/
obj-y += freescale/
obj-$(CONFIG_X86) += intel/
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -0,0 +1,3 @@
+config PINCTRL_BCM63XX
+ bool
+ select GPIO_GENERIC
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
@@ -0,0 +1,155 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/gpio/driver.h>
+#include <linux/of_irq.h>
+
+#include "pinctrl-bcm63xx.h"
+#include "../core.h"
+
+#define BANK_SIZE sizeof(u32)
+#define PINS_PER_BANK (BANK_SIZE * BITS_PER_BYTE)
+
+#ifdef CONFIG_OF
+static int bcm63xx_gpio_of_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec,
+ u32 *flags)
+{
+ struct gpio_chip *base = gpiochip_get_data(gc);
+ int pin = gpiospec->args[0];
+
+ if (gc != &base[pin / PINS_PER_BANK])
+ return -EINVAL;
+
+ pin = pin % PINS_PER_BANK;
+
+ if (pin >= gc->ngpio)
+ return -EINVAL;
+
+ if (flags)
+ *flags = gpiospec->args[1];
+
+ return pin;
+}
+#endif
+
+static int bcm63xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+ struct gpio_chip *base = gpiochip_get_data(chip);
+ char irq_name[7]; /* "gpioXX" */
+
+ /* FIXME: this is ugly */
+ sprintf(irq_name, "gpio%d", gpio + PINS_PER_BANK * (chip - base));
+ return of_irq_get_byname(chip->of_node, irq_name);
+}
+
+static int bcm63xx_setup_gpio(struct device *dev, struct gpio_chip *gc,
+ void __iomem *dirout, void __iomem *data,
+ size_t sz, int ngpio)
+
+{
+ int banks, chips, i, ret = -EINVAL;
+
+ chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
+ banks = sz / BANK_SIZE;
+
+ for (i = 0; i < chips; i++) {
+ int offset, pins;
+ int reg_offset;
+ char *label;
+
+ label = devm_kasprintf(dev, GFP_KERNEL, "bcm63xx-gpio.%i", i);
+ if (!label)
+ return -ENOMEM;
+
+ offset = i * PINS_PER_BANK;
+ pins = min_t(int, ngpio - offset, PINS_PER_BANK);
+
+ /* the registers are treated like a huge big endian register */
+ reg_offset = (banks - i - 1) * BANK_SIZE;
+
+ ret = bgpio_init(&gc[i], dev, BANK_SIZE, data + reg_offset,
+ NULL, NULL, dirout + reg_offset, NULL,
+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
+ if (ret)
+ return ret;
+
+ gc[i].request = gpiochip_generic_request;
+ gc[i].free = gpiochip_generic_free;
+
+ if (of_get_property(dev->of_node, "interrupt-names", NULL))
+ gc[i].to_irq = bcm63xx_gpio_to_irq;
+
+#ifdef CONFIG_OF
+ gc[i].of_gpio_n_cells = 2;
+ gc[i].of_xlate = bcm63xx_gpio_of_xlate;
+#endif
+
+ gc[i].label = label;
+ gc[i].ngpio = pins;
+
+ devm_gpiochip_add_data(dev, &gc[i], gc);
+ }
+
+ return 0;
+}
+
+static void bcm63xx_setup_pinranges(struct gpio_chip *gc, const char *name,
+ int ngpio)
+{
+ int i, chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
+
+ for (i = 0; i < chips; i++) {
+ int offset, pins;
+
+ offset = i * PINS_PER_BANK;
+ pins = min_t(int, ngpio - offset, PINS_PER_BANK);
+
+ gpiochip_add_pin_range(&gc[i], name, 0, offset, pins);
+ }
+}
+
+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
+ struct pinctrl_desc *desc,
+ void *priv, struct gpio_chip *gc,
+ int ngpio)
+{
+ struct pinctrl_dev *pctldev;
+ struct resource *res;
+ void __iomem *dirout, *data;
+ size_t sz;
+ int ret;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirout");
+ dirout = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(dirout))
+ return ERR_CAST(dirout);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
+ data = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data))
+ return ERR_CAST(data);
+
+ sz = resource_size(res);
+
+ ret = bcm63xx_setup_gpio(&pdev->dev, gc, dirout, data, sz, ngpio);
+ if (ret)
+ return ERR_PTR(ret);
+
+ pctldev = devm_pinctrl_register(&pdev->dev, desc, priv);
+ if (IS_ERR(pctldev))
+ return pctldev;
+
+ bcm63xx_setup_pinranges(gc, pinctrl_dev_get_devname(pctldev), ngpio);
+
+ dev_info(&pdev->dev, "registered at mmio %p\n", dirout);
+
+ return pctldev;
+}
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
@@ -0,0 +1,14 @@
+#ifndef __PINCTRL_BCM63XX
+#define __PINCTRL_BCM63XX
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
+ struct pinctrl_desc *desc,
+ void *priv, struct gpio_chip *gc,
+ int ngpio);
+
+#endif

View file

@ -1,78 +0,0 @@
From 4bdd40849632608d5cb7d3a64380cd76e7eea07b Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:33:56 +0200
Subject: [PATCH 02/16] Documentation: add BCM6328 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6328 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6328-pinctrl.txt | 61 ++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.txt
@@ -0,0 +1,61 @@
+* Broadcom BCM6328 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6328-pinctrl".
+- reg: Register specifies of dirout, dat, mode, mux registers.
+- reg-names: Must be "dirout", "dat", "mode", "mux".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6328-pinctrl";
+ reg = <0x10000080 0x8>,
+ <0x10000088 0x8>,
+ <0x10000098 0x4>,
+ <0x1000009c 0xc>;
+ reg-names = "dirout", "dat", "mode", "mux";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led
+gpio1 1 led
+gpio2 2 led
+gpio3 3 led
+gpio4 4 led
+gpio5 5 led
+gpio6 6 led, serial_led_data
+gpio7 7 led, serial_led_clk
+gpio8 8 led
+gpio9 9 led
+gpio10 10 led
+gpio11 11 led
+gpio12 12 led
+gpio13 13 led
+gpio14 14 led
+gpio15 15 led
+gpio16 16 led, pcie_clkreq
+gpio17 17 led
+gpio18 18 led
+gpio19 19 led
+gpio20 20 led
+gpio21 21 led
+gpio22 22 led
+gpio23 23 led
+gpio24 24 -
+gpio25 25 ephy0_act_led
+gpio26 26 ephy1_act_led
+gpio27 27 ephy2_act_led
+gpio28 28 ephy3_act_led
+gpio29 29 -
+gpio30 30 -
+gpio31 31 -
+hsspi_cs1 - hsspi_cs1
+usb_port1 - usb_host_port, usb_device_port

View file

@ -1,495 +0,0 @@
From 393e9753f6492c1fdf55891ddee60d955ae8b119 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:12:50 +0200
Subject: [PATCH 03/16] pinctrl: add a pincontrol driver for BCM6328
Add a pincontrol driver for BCM6328. BCM628 supports muxing 32 pins as
GPIOs, as LEDs for the integrated LED controller, or various other
functions. Its pincontrol mux registers also control other aspects, like
switching the second USB port between host and device mode.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 7 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c | 456 ++++++++++++++++++++++++++++++
3 files changed, 464 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -1,3 +1,10 @@
config PINCTRL_BCM63XX
bool
select GPIO_GENERIC
+
+config PINCTRL_BCM6328
+ bool "BCM6328 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
+obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c
@@ -0,0 +1,456 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6328_MUX_LO_REG 0x4
+#define BCM6328_MUX_HI_REG 0x0
+#define BCM6328_MUX_OTHER_REG 0x8
+
+#define BCM6328_NGPIO 32
+
+struct bcm6328_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6328_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ unsigned mode_val:1;
+ unsigned mux_val:2;
+};
+
+struct bcm6328_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *mode;
+ void __iomem *mux[3];
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio;
+};
+
+static const struct pinctrl_pin_desc bcm6328_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+
+ /*
+ * No idea where they really are; so let's put them according
+ * to their mux offsets.
+ */
+ PINCTRL_PIN(36, "hsspi_cs1"),
+ PINCTRL_PIN(38, "usb_p2"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+
+static unsigned hsspi_cs1_pins[] = { 36 };
+static unsigned usb_port1_pins[] = { 38 };
+
+#define BCM6328_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6328_pingroup bcm6328_groups[] = {
+ BCM6328_GROUP(gpio0),
+ BCM6328_GROUP(gpio1),
+ BCM6328_GROUP(gpio2),
+ BCM6328_GROUP(gpio3),
+ BCM6328_GROUP(gpio4),
+ BCM6328_GROUP(gpio5),
+ BCM6328_GROUP(gpio6),
+ BCM6328_GROUP(gpio7),
+ BCM6328_GROUP(gpio8),
+ BCM6328_GROUP(gpio9),
+ BCM6328_GROUP(gpio10),
+ BCM6328_GROUP(gpio11),
+ BCM6328_GROUP(gpio12),
+ BCM6328_GROUP(gpio13),
+ BCM6328_GROUP(gpio14),
+ BCM6328_GROUP(gpio15),
+ BCM6328_GROUP(gpio16),
+ BCM6328_GROUP(gpio17),
+ BCM6328_GROUP(gpio18),
+ BCM6328_GROUP(gpio19),
+ BCM6328_GROUP(gpio20),
+ BCM6328_GROUP(gpio21),
+ BCM6328_GROUP(gpio22),
+ BCM6328_GROUP(gpio23),
+ BCM6328_GROUP(gpio24),
+ BCM6328_GROUP(gpio25),
+ BCM6328_GROUP(gpio26),
+ BCM6328_GROUP(gpio27),
+ BCM6328_GROUP(gpio28),
+ BCM6328_GROUP(gpio29),
+ BCM6328_GROUP(gpio30),
+ BCM6328_GROUP(gpio31),
+
+ BCM6328_GROUP(hsspi_cs1),
+ BCM6328_GROUP(usb_port1),
+};
+
+/* GPIO_MODE */
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+/* PINMUX_SEL */
+static const char * const serial_led_data_groups[] = {
+ "gpio6",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio7",
+};
+
+static const char * const inet_act_led_groups[] = {
+ "gpio11",
+};
+
+static const char * const pcie_clkreq_groups[] = {
+ "gpio16",
+};
+
+static const char * const ephy0_act_led_groups[] = {
+ "gpio25",
+};
+
+static const char * const ephy1_act_led_groups[] = {
+ "gpio26",
+};
+
+static const char * const ephy2_act_led_groups[] = {
+ "gpio27",
+};
+
+static const char * const ephy3_act_led_groups[] = {
+ "gpio28",
+};
+
+static const char * const hsspi_cs1_groups[] = {
+ "hsspi_cs1"
+};
+
+static const char * const usb_host_port_groups[] = {
+ "usb_port1",
+};
+
+static const char * const usb_device_port_groups[] = {
+ "usb_port1",
+};
+
+#define BCM6328_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .mode_val = 1, \
+ }
+
+#define BCM6328_MUX_FUN(n, mux) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .mux_val = mux, \
+ }
+
+static const struct bcm6328_function bcm6328_funcs[] = {
+ BCM6328_MODE_FUN(led),
+ BCM6328_MUX_FUN(serial_led_data, 2),
+ BCM6328_MUX_FUN(serial_led_clk, 2),
+ BCM6328_MUX_FUN(inet_act_led, 1),
+ BCM6328_MUX_FUN(pcie_clkreq, 2),
+ BCM6328_MUX_FUN(ephy0_act_led, 1),
+ BCM6328_MUX_FUN(ephy1_act_led, 1),
+ BCM6328_MUX_FUN(ephy2_act_led, 1),
+ BCM6328_MUX_FUN(ephy3_act_led, 1),
+ BCM6328_MUX_FUN(hsspi_cs1, 2),
+ BCM6328_MUX_FUN(usb_host_port, 1),
+ BCM6328_MUX_FUN(usb_device_port, 2),
+};
+
+static int bcm6328_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6328_groups);
+}
+
+static const char *bcm6328_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6328_groups[group].name;
+}
+
+static int bcm6328_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6328_groups[group].pins;
+ *num_pins = bcm6328_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6328_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6328_funcs);
+}
+
+static const char *bcm6328_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6328_funcs[selector].name;
+}
+
+static int bcm6328_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6328_funcs[selector].groups;
+ *num_groups = bcm6328_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6328_rmw_mux(struct bcm6328_pinctrl *pctl, unsigned pin,
+ u32 mode, u32 mux)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ if (pin < 32) {
+ reg = __raw_readl(pctl->mode);
+ reg &= ~BIT(pin);
+ if (mode)
+ reg |= BIT(pin);
+ __raw_writel(reg, pctl->mode);
+ }
+
+ reg = __raw_readl(pctl->mux[pin / 16]);
+ reg &= ~(3UL << ((pin % 16) * 2));
+ reg |= mux << ((pin % 16) * 2);
+ __raw_writel(reg, pctl->mux[pin / 16]);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static int bcm6328_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6328_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6328_pingroup *grp = &bcm6328_groups[group];
+ const struct bcm6328_function *f = &bcm6328_funcs[selector];
+
+ bcm6328_rmw_mux(pctl, grp->pins[0], f->mode_val, f->mux_val);
+
+ return 0;
+}
+
+static int bcm6328_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6328_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ bcm6328_rmw_mux(pctl, offset, 0, 0);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6328_pctl_ops = {
+ .get_groups_count = bcm6328_pinctrl_get_group_count,
+ .get_group_name = bcm6328_pinctrl_get_group_name,
+ .get_group_pins = bcm6328_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6328_pmx_ops = {
+ .get_functions_count = bcm6328_pinctrl_get_func_count,
+ .get_function_name = bcm6328_pinctrl_get_func_name,
+ .get_function_groups = bcm6328_pinctrl_get_groups,
+ .set_mux = bcm6328_pinctrl_set_mux,
+ .gpio_request_enable = bcm6328_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6328_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6328_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *mode, *mux;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mux");
+ mux = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mux))
+ return PTR_ERR(mux);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->mode = mode;
+ pctl->mux[0] = mux + BCM6328_MUX_LO_REG;
+ pctl->mux[1] = mux + BCM6328_MUX_HI_REG;
+ pctl->mux[2] = mux + BCM6328_MUX_OTHER_REG;
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6328_pctl_ops;
+ pctl->desc.pmxops = &bcm6328_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6328_pins);
+ pctl->desc.pins = bcm6328_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ &pctl->gpio, BCM6328_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6328_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6328-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6328_pinctrl_driver = {
+ .probe = bcm6328_pinctrl_probe,
+ .driver = {
+ .name = "bcm6328-pinctrl",
+ .of_match_table = bcm6328_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6328_pinctrl_driver);

View file

@ -1,49 +0,0 @@
From 962c46bf7f43df730e2d3698930e77958cc6b191 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:35:45 +0200
Subject: [PATCH 04/16] Documentation: add BCM6348 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6348 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6348-pinctrl.txt | 32 ++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6348-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6348-pinctrl.txt
@@ -0,0 +1,32 @@
+* Broadcom BCM6348 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6348-pinctrl".
+- reg: register Specifiers of dirout, dat, mode registers.
+- reg-names: Must be "dirout", "dat", "mode".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@fffe0080 {
+ compatible = "brcm,bcm6348-pinctrl";
+ reg = <0xfffe0080 0x8>,
+ <0xfffe0088 0x8>,
+ <0xfffe0098 0x4>;
+ reg-names = "dirout", "dat", "mode";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+group0 32-36 ext_mii, diag
+group1 22-31 ext_ephy, mii_snoop, mii_pccard,
+ spi_master_uart, utopia, diag
+group2 16-21 pci, diag
+group3 8-15 ext_mii, utopia, diag
+group4 0-7 ext_ephy, mii_snoop, legacy_led, utopia, diag

View file

@ -1,410 +0,0 @@
From 45444cb631555e2dc16b95d779b10aa075c7482e Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:14:13 +0200
Subject: [PATCH 05/16] pinctrl: add a pincontrol driver for BCM6348
Add a pincotrol driver for BCM6348. BCM6348 allow muxing five groups of
up to ten gpios into fourteen potential functions. It does not allow
muxing individual pins. Some functions require more than one group to be
muxed to the same function.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 7 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6348.c | 391 ++++++++++++++++++++++++++++++
3 files changed, 399 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6348.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -8,3 +8,10 @@ config PINCTRL_BCM6328
select PINCONF
select PINCTRL_BCM63XX
select GENERIC_PINCONF
+
+config PINCTRL_BCM6348
+ bool "BCM6348 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
+obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6348.c
@@ -0,0 +1,370 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6348_NGPIO 37
+
+#define MAX_GROUP 4
+#define PINS_PER_GROUP 8
+#define PIN_TO_GROUP(pin) (MAX_GROUP - ((pin) / PINS_PER_GROUP))
+#define GROUP_SHIFT(pin) (PIN_TO_GROUP(pin) * 4)
+#define GROUP_MASK(pin) (0xf << GROUP_SHIFT(pin))
+
+struct bcm6348_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6348_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+ unsigned int value;
+};
+
+struct bcm6348_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *mode;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6348_PIN(a, b, group) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(group), \
+ }
+
+static const struct pinctrl_pin_desc bcm6348_pins[] = {
+ BCM6348_PIN(0, "gpio0", 4),
+ BCM6348_PIN(1, "gpio1", 4),
+ BCM6348_PIN(2, "gpio2", 4),
+ BCM6348_PIN(3, "gpio3", 4),
+ BCM6348_PIN(4, "gpio4", 4),
+ BCM6348_PIN(5, "gpio5", 4),
+ BCM6348_PIN(6, "gpio6", 4),
+ BCM6348_PIN(7, "gpio7", 4),
+ BCM6348_PIN(8, "gpio8", 3),
+ BCM6348_PIN(9, "gpio9", 3),
+ BCM6348_PIN(10, "gpio10", 3),
+ BCM6348_PIN(11, "gpio11", 3),
+ BCM6348_PIN(12, "gpio12", 3),
+ BCM6348_PIN(13, "gpio13", 3),
+ BCM6348_PIN(14, "gpio14", 3),
+ BCM6348_PIN(15, "gpio15", 3),
+ BCM6348_PIN(16, "gpio16", 2),
+ BCM6348_PIN(17, "gpio17", 2),
+ BCM6348_PIN(18, "gpio18", 2),
+ BCM6348_PIN(19, "gpio19", 2),
+ BCM6348_PIN(20, "gpio20", 2),
+ BCM6348_PIN(21, "gpio21", 2),
+ BCM6348_PIN(22, "gpio22", 1),
+ BCM6348_PIN(23, "gpio23", 1),
+ BCM6348_PIN(24, "gpio24", 1),
+ BCM6348_PIN(25, "gpio25", 1),
+ BCM6348_PIN(26, "gpio26", 1),
+ BCM6348_PIN(27, "gpio27", 1),
+ BCM6348_PIN(28, "gpio28", 1),
+ BCM6348_PIN(29, "gpio29", 1),
+ BCM6348_PIN(30, "gpio30", 1),
+ BCM6348_PIN(31, "gpio31", 1),
+ BCM6348_PIN(32, "gpio32", 0),
+ BCM6348_PIN(33, "gpio33", 0),
+ BCM6348_PIN(34, "gpio34", 0),
+ BCM6348_PIN(35, "gpio35", 0),
+ BCM6348_PIN(36, "gpio36", 0),
+};
+
+enum bcm6348_muxes {
+ BCM6348_MUX_GPIO = 0,
+ BCM6348_MUX_EXT_EPHY,
+ BCM6348_MUX_MII_SNOOP,
+ BCM6348_MUX_LEGACY_LED,
+ BCM6348_MUX_MII_PCCARD,
+ BCM6348_MUX_PCI,
+ BCM6348_MUX_SPI_MASTER_UART,
+ BCM6348_MUX_EXT_MII,
+ BCM6348_MUX_UTOPIA,
+ BCM6348_MUX_DIAG,
+};
+
+static unsigned group0_pins[] = {
+ 32, 33, 34, 35, 36,
+};
+
+static unsigned group1_pins[] = {
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+};
+
+static unsigned group2_pins[] = {
+ 16, 17, 18, 19, 20, 21,
+};
+
+static unsigned group3_pins[] = {
+ 8, 9, 10, 11, 12, 13, 14, 15,
+};
+
+static unsigned group4_pins[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+};
+
+#define BCM6348_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ } \
+
+static struct bcm6348_pingroup bcm6348_groups[] = {
+ BCM6348_GROUP(group0),
+ BCM6348_GROUP(group1),
+ BCM6348_GROUP(group2),
+ BCM6348_GROUP(group3),
+ BCM6348_GROUP(group4),
+};
+
+static const char * const ext_mii_groups[] = {
+ "group0",
+ "group3",
+};
+
+static const char * const ext_ephy_groups[] = {
+ "group1",
+ "group4"
+};
+
+static const char * const mii_snoop_groups[] = {
+ "group1",
+ "group4",
+};
+
+static const char * const legacy_led_groups[] = {
+ "group4",
+};
+
+static const char * const mii_pccard_groups[] = {
+ "group1",
+};
+
+static const char * const pci_groups[] = {
+ "group2",
+};
+
+static const char * const spi_master_uart_groups[] = {
+ "group1",
+};
+
+static const char * const utopia_groups[] = {
+ "group1",
+ "group3",
+ "group4",
+};
+
+static const char * const diag_groups[] = {
+ "group0",
+ "group1",
+ "group2",
+ "group3",
+ "group4",
+};
+
+#define BCM6348_FUN(n, f) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .value = BCM6348_MUX_##f, \
+ }
+
+static const struct bcm6348_function bcm6348_funcs[] = {
+ BCM6348_FUN(ext_mii, EXT_MII),
+ BCM6348_FUN(ext_ephy, EXT_EPHY),
+ BCM6348_FUN(mii_snoop, MII_SNOOP),
+ BCM6348_FUN(legacy_led, LEGACY_LED),
+ BCM6348_FUN(mii_pccard, MII_PCCARD),
+ BCM6348_FUN(pci, PCI),
+ BCM6348_FUN(spi_master_uart, SPI_MASTER_UART),
+ BCM6348_FUN(utopia, UTOPIA),
+ BCM6348_FUN(diag, DIAG),
+};
+
+static int bcm6348_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6348_groups);
+}
+
+static const char *bcm6348_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6348_groups[group].name;
+}
+
+static int bcm6348_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6348_groups[group].pins;
+ *num_pins = bcm6348_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6348_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6348_funcs);
+}
+
+static const char *bcm6348_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6348_funcs[selector].name;
+}
+
+static int bcm6348_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6348_funcs[selector].groups;
+ *num_groups = bcm6348_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6348_rmw_mux(struct bcm6348_pinctrl *pctl, u32 mask, u32 val)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+
+ reg = __raw_readl(pctl->mode);
+ reg &= ~mask;
+ reg |= val & mask;
+ __raw_writel(reg, pctl->mode);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static int bcm6348_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6348_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6348_pingroup *grp = &bcm6348_groups[group];
+ const struct bcm6348_function *f = &bcm6348_funcs[selector];
+ u32 mask, val;
+
+ /*
+ * pins n..(n+7) share the same group, so we only need to look at
+ * the first pin.
+ */
+ mask = GROUP_MASK(grp->pins[0]);
+ val = f->value << GROUP_SHIFT(grp->pins[0]);
+
+ bcm6348_rmw_mux(pctl, mask, val);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6348_pctl_ops = {
+ .get_groups_count = bcm6348_pinctrl_get_group_count,
+ .get_group_name = bcm6348_pinctrl_get_group_name,
+ .get_group_pins = bcm6348_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6348_pmx_ops = {
+ .get_functions_count = bcm6348_pinctrl_get_func_count,
+ .get_function_name = bcm6348_pinctrl_get_func_name,
+ .get_function_groups = bcm6348_pinctrl_get_groups,
+ .set_mux = bcm6348_pinctrl_set_mux,
+ .strict = false,
+};
+
+static int bcm6348_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6348_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *mode;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->mode = mode;
+
+ /* disable all muxes by default */
+ __raw_writel(0, pctl->mode);
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6348_pctl_ops;
+ pctl->desc.pmxops = &bcm6348_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6348_pins);
+ pctl->desc.pins = bcm6348_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6348_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6348_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6348-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6348_pinctrl_driver = {
+ .probe = bcm6348_pinctrl_probe,
+ .driver = {
+ .name = "bcm6348-pinctrl",
+ .of_match_table = bcm6348_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6348_pinctrl_driver);

View file

@ -1,61 +0,0 @@
From c7c8fa7f5b5ee9bea751fa7bdae8ff4acde8f26e Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:36:00 +0200
Subject: [PATCH 06/16] Documentation: add BCM6358 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6358 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6358-pinctrl.txt | 44 ++++++++++++++++++++++
1 file changed, 44 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.txt
@@ -0,0 +1,44 @@
+* Broadcom BCM6358 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6358-pinctrl".
+- reg: Register specifiers of dirout, dat registers.
+- reg-names: Must be "dirout", "dat".
+- brcm,gpiomode: Phandle to the shared gpiomode register.
+- gpio-controller: Identifies this node as a gpio-controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@fffe0080 {
+ compatible = "brcm,bcm6358-pinctrl";
+ reg = <0xfffe0080 0x8>,
+ <0xfffe0088 0x8>,
+ <0xfffe0098 0x4>;
+ reg-names = "dirout", "dat";
+ brcm,gpiomode = <&gpiomode>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+gpiomode: syscon@fffe0098 {
+ compatible = "brcm,bcm6358-gpiomode", "syscon";
+ reg = <0xfffe0098 0x4>;
+ native-endian;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+ebi_cs_grp 30-31 ebi_cs
+uart1_grp 28-31 uart1
+spi_cs_grp 32-33 spi_cs
+async_modem_grp 12-15 async_modem
+legacy_led_grp 9-15 legacy_led
+serial_led_grp 6-7 serial_led
+led_grp 0-3 led
+utopia_grp 12-15, 22-31 utopia
+pwm_syn_clk_grp 8 pwm_syn_clk
+sys_irq_grp 5 sys_irq

View file

@ -1,436 +0,0 @@
From fb00ef462f3f8b70ea8902151cc72810fe90b999 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:16:01 +0200
Subject: [PATCH 07/16] pinctrl: add a pincontrol driver for BCM6358
Add a pincotrol driver for BCM6358. BCM6358 allow overlaying different
functions onto the GPIO pins. It does not support configuring individual
pins but only whole groups. These groups may overlap, and still require
the directions to be set correctly in the GPIO register. In addition the
functions register controls other, not directly mux related functions.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 8 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c | 393 ++++++++++++++++++++++++++++++
3 files changed, 402 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -15,3 +15,11 @@ config PINCTRL_BCM6348
select PINCONF
select PINCTRL_BCM63XX
select GENERIC_PINCONF
+
+config PINCTRL_BCM6358
+ bool "BCM6358 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
+ select MFD_SYSCON
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
+obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c
@@ -0,0 +1,393 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+/* GPIO_MODE register */
+#define BCM6358_MODE_MUX_NONE 0
+
+/* overlays on gpio pins */
+#define BCM6358_MODE_MUX_EBI_CS BIT(5)
+#define BCM6358_MODE_MUX_UART1 BIT(6)
+#define BCM6358_MODE_MUX_SPI_CS BIT(7)
+#define BCM6358_MODE_MUX_ASYNC_MODEM BIT(8)
+#define BCM6358_MODE_MUX_LEGACY_LED BIT(9)
+#define BCM6358_MODE_MUX_SERIAL_LED BIT(10)
+#define BCM6358_MODE_MUX_LED BIT(11)
+#define BCM6358_MODE_MUX_UTOPIA BIT(12)
+#define BCM6358_MODE_MUX_CLKRST BIT(13)
+#define BCM6358_MODE_MUX_PWM_SYN_CLK BIT(14)
+#define BCM6358_MODE_MUX_SYS_IRQ BIT(15)
+
+#define BCM6358_NGPIO 40
+
+struct bcm6358_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+
+ const u16 mode_val;
+
+ /* non-GPIO function muxes require the gpio direction to be set */
+ const u16 direction;
+};
+
+struct bcm6358_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+};
+
+struct bcm6358_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ struct regmap_field *overlays;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6358_GPIO_PIN(a, b, bit1, bit2, bit3) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(BCM6358_MODE_MUX_##bit1 | \
+ BCM6358_MODE_MUX_##bit2 | \
+ BCM6358_MODE_MUX_##bit3), \
+ }
+
+static const struct pinctrl_pin_desc bcm6358_pins[] = {
+ BCM6358_GPIO_PIN(0, "gpio0", LED, NONE, NONE),
+ BCM6358_GPIO_PIN(1, "gpio1", LED, NONE, NONE),
+ BCM6358_GPIO_PIN(2, "gpio2", LED, NONE, NONE),
+ BCM6358_GPIO_PIN(3, "gpio3", LED, NONE, NONE),
+ PINCTRL_PIN(4, "gpio4"),
+ BCM6358_GPIO_PIN(5, "gpio5", SYS_IRQ, NONE, NONE),
+ BCM6358_GPIO_PIN(6, "gpio6", SERIAL_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(7, "gpio7", SERIAL_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(8, "gpio8", PWM_SYN_CLK, NONE, NONE),
+ BCM6358_GPIO_PIN(9, "gpio09", LEGACY_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(10, "gpio10", LEGACY_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(11, "gpio11", LEGACY_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(12, "gpio12", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ BCM6358_GPIO_PIN(13, "gpio13", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ BCM6358_GPIO_PIN(14, "gpio14", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ BCM6358_GPIO_PIN(15, "gpio15", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ BCM6358_GPIO_PIN(22, "gpio22", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(23, "gpio23", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(24, "gpio24", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(25, "gpio25", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(26, "gpio26", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(27, "gpio27", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(28, "gpio28", UTOPIA, UART1, NONE),
+ BCM6358_GPIO_PIN(29, "gpio29", UTOPIA, UART1, NONE),
+ BCM6358_GPIO_PIN(30, "gpio30", UTOPIA, UART1, EBI_CS),
+ BCM6358_GPIO_PIN(31, "gpio31", UTOPIA, UART1, EBI_CS),
+ BCM6358_GPIO_PIN(32, "gpio32", SPI_CS, NONE, NONE),
+ BCM6358_GPIO_PIN(33, "gpio33", SPI_CS, NONE, NONE),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+};
+
+static unsigned ebi_cs_grp_pins[] = { 30, 31 };
+
+static unsigned uart1_grp_pins[] = { 28, 29, 30, 31 };
+
+static unsigned spi_cs_grp_pins[] = { 32, 33 };
+
+static unsigned async_modem_grp_pins[] = { 12, 13, 14, 15 };
+
+static unsigned serial_led_grp_pins[] = { 6, 7 };
+
+static unsigned legacy_led_grp_pins[] = { 9, 10, 11, 12, 13, 14, 15 };
+
+static unsigned led_grp_pins[] = { 0, 1, 2, 3 };
+
+static unsigned utopia_grp_pins[] = {
+ 12, 13, 14, 15, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+};
+
+static unsigned pwm_syn_clk_grp_pins[] = { 8 };
+
+static unsigned sys_irq_grp_pins[] = { 5 };
+
+#define BCM6358_GPIO_MUX_GROUP(n, bit, dir) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ .mode_val = BCM6358_MODE_MUX_##bit, \
+ .direction = dir, \
+ }
+
+static const struct bcm6358_pingroup bcm6358_groups[] = {
+ BCM6358_GPIO_MUX_GROUP(ebi_cs_grp, EBI_CS, 0x3),
+ BCM6358_GPIO_MUX_GROUP(uart1_grp, UART1, 0x2),
+ BCM6358_GPIO_MUX_GROUP(spi_cs_grp, SPI_CS, 0x6),
+ BCM6358_GPIO_MUX_GROUP(async_modem_grp, ASYNC_MODEM, 0x6),
+ BCM6358_GPIO_MUX_GROUP(legacy_led_grp, LEGACY_LED, 0x7f),
+ BCM6358_GPIO_MUX_GROUP(serial_led_grp, SERIAL_LED, 0x3),
+ BCM6358_GPIO_MUX_GROUP(led_grp, LED, 0xf),
+ BCM6358_GPIO_MUX_GROUP(utopia_grp, UTOPIA, 0x000f),
+ BCM6358_GPIO_MUX_GROUP(pwm_syn_clk_grp, PWM_SYN_CLK, 0x1),
+ BCM6358_GPIO_MUX_GROUP(sys_irq_grp, SYS_IRQ, 0x1),
+};
+
+static const char * const ebi_cs_groups[] = {
+ "ebi_cs_grp"
+};
+
+static const char * const uart1_groups[] = {
+ "uart1_grp"
+};
+
+static const char * const spi_cs_2_3_groups[] = {
+ "spi_cs_2_3_grp"
+};
+
+static const char * const async_modem_groups[] = {
+ "async_modem_grp"
+};
+
+static const char * const legacy_led_groups[] = {
+ "legacy_led_grp",
+};
+
+static const char * const serial_led_groups[] = {
+ "serial_led_grp",
+};
+
+static const char * const led_groups[] = {
+ "led_grp",
+};
+
+static const char * const clkrst_groups[] = {
+ "clkrst_grp",
+};
+
+static const char * const pwm_syn_clk_groups[] = {
+ "pwm_syn_clk_grp",
+};
+
+static const char * const sys_irq_groups[] = {
+ "sys_irq_grp",
+};
+
+#define BCM6358_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ }
+
+static const struct bcm6358_function bcm6358_funcs[] = {
+ BCM6358_FUN(ebi_cs),
+ BCM6358_FUN(uart1),
+ BCM6358_FUN(spi_cs_2_3),
+ BCM6358_FUN(async_modem),
+ BCM6358_FUN(legacy_led),
+ BCM6358_FUN(serial_led),
+ BCM6358_FUN(led),
+ BCM6358_FUN(clkrst),
+ BCM6358_FUN(pwm_syn_clk),
+ BCM6358_FUN(sys_irq),
+};
+
+static int bcm6358_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6358_groups);
+}
+
+static const char *bcm6358_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6358_groups[group].name;
+}
+
+static int bcm6358_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6358_groups[group].pins;
+ *num_pins = bcm6358_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6358_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6358_funcs);
+}
+
+static const char *bcm6358_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6358_funcs[selector].name;
+}
+
+static int bcm6358_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6358_funcs[selector].groups;
+ *num_groups = bcm6358_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static int bcm6358_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6358_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6358_pingroup *grp = &bcm6358_groups[group];
+ u32 val = grp->mode_val;
+ u32 mask = val;
+ unsigned pin;
+
+ for (pin = 0; pin < grp->num_pins; pin++)
+ mask |= (unsigned long)bcm6358_pins[pin].drv_data;
+
+ regmap_field_update_bits(pctl->overlays, mask, val);
+
+ for (pin = 0; pin < grp->num_pins; pin++) {
+ int hw_gpio = bcm6358_pins[pin].number;
+ struct gpio_chip *gc = &pctl->gpio[hw_gpio / 32];
+
+ if (grp->direction & BIT(pin))
+ gc->direction_output(gc, hw_gpio % 32, 0);
+ else
+ gc->direction_input(gc, hw_gpio % 32);
+ }
+
+ return 0;
+}
+
+static int bcm6358_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6358_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ u32 mask;
+
+ mask = (unsigned long)bcm6358_pins[offset].drv_data;
+ if (!mask)
+ return 0;
+
+ /* disable all functions using this pin */
+ return regmap_field_update_bits(pctl->overlays, mask, 0);
+}
+
+static struct pinctrl_ops bcm6358_pctl_ops = {
+ .get_groups_count = bcm6358_pinctrl_get_group_count,
+ .get_group_name = bcm6358_pinctrl_get_group_name,
+ .get_group_pins = bcm6358_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6358_pmx_ops = {
+ .get_functions_count = bcm6358_pinctrl_get_func_count,
+ .get_function_name = bcm6358_pinctrl_get_func_name,
+ .get_function_groups = bcm6358_pinctrl_get_groups,
+ .set_mux = bcm6358_pinctrl_set_mux,
+ .gpio_request_enable = bcm6358_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6358_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6358_pinctrl *pctl;
+ struct regmap *mode;
+ struct reg_field overlays = REG_FIELD(0, 0, 15);
+
+ if (pdev->dev.of_node)
+ mode = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "brcm,gpiomode");
+ else
+ mode = syscon_regmap_lookup_by_pdevname("syscon.fffe0098");
+
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ pctl->overlays = devm_regmap_field_alloc(&pdev->dev, mode, overlays);
+ if (IS_ERR(pctl->overlays))
+ return PTR_ERR(pctl->overlays);
+
+ /* disable all muxes by default */
+ regmap_field_write(pctl->overlays, 0);
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6358_pctl_ops;
+ pctl->desc.pmxops = &bcm6358_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6358_pins);
+ pctl->desc.pins = bcm6358_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6358_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6358_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6358-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6358_pinctrl_driver = {
+ .probe = bcm6358_pinctrl_probe,
+ .driver = {
+ .name = "bcm6358-pinctrl",
+ .of_match_table = bcm6358_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6358_pinctrl_driver);

View file

@ -1,96 +0,0 @@
From ba03ea8ada2ca71c9095d96a1e4085c2c5cf0e69 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:36:18 +0200
Subject: [PATCH 08/16] Documentation: add BCM6362 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6362 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6362-pinctrl.txt | 79 ++++++++++++++++++++++
1 file changed, 79 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.txt
@@ -0,0 +1,79 @@
+* Broadcom BCM6362 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6362-pinctrl"
+- reg: Register specifiers of dirout, dat, led, mode, ctrl, basemode registers.
+- reg-names: Must be "dirout", "dat", "led", "mode", "ctrl", "basemode".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6362-pinctrl";
+ reg = <0x10000080 0x8>,
+ <0x10000088 0x8>,
+ <0x10000090 0x4>,
+ <0x10000098 0x4>,
+ <0x1000009c 0x4>,
+ <0x100000b8 0x4>;
+ reg-names = "dirout", "dat", "led",
+ "mode", "ctrl", "basemode";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led, usb_device_led
+gpio1 1 led, sys_irq
+gpio2 2 led, serial_led_clk
+gpio3 3 led, serial_led_data
+gpio4 4 led, robosw_led_data
+gpio5 5 led, robosw_led_clk
+gpio6 6 led, robosw_led0
+gpio7 7 led, robosw_led1
+gpio8 8 led, inet_led
+gpio9 9 led, spi_cs2
+gpio10 10 led, spi_cs3
+gpio11 11 led, ntr_pulse
+gpio12 12 led, uart1_scts
+gpio13 13 led, uart1_srts
+gpio14 14 led, uart1_sdin
+gpio15 15 led, uart1_sdout
+gpio16 16 led, adsl_spi_miso
+gpio17 17 led, adsl_spi_mosi
+gpio18 18 led, adsl_spi_clk
+gpio19 19 led, adsl_spi_cs
+gpio20 20 led, ephy0_led
+gpio21 21 led, ephy1_led
+gpio22 22 led, ephy2_led
+gpio23 23 led, ephy3_led
+gpio24 24 ext_irq0
+gpio25 25 ext_irq1
+gpio26 26 ext_irq2
+gpio27 27 ext_irq3
+gpio28 28 -
+gpio29 29 -
+gpio30 30 -
+gpio31 31 -
+gpio32 32 wifi
+gpio33 33 wifi
+gpio34 34 wifi
+gpio35 35 wifi
+gpio36 36 wifi
+gpio37 37 wifi
+gpio38 38 wifi
+gpio39 39 wifi
+gpio40 40 wifi
+gpio41 41 wifi
+gpio42 42 wifi
+gpio43 43 wifi
+gpio44 44 wifi
+gpio45 45 wifi
+gpio46 46 wifi
+gpio47 47 wifi
+nand_grp 8, 12-23, 27 nand

View file

@ -1,733 +0,0 @@
From eea6b96701d734095e2f823f3a82d9b063f553ae Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:17:20 +0200
Subject: [PATCH 09/16] pinctrl: add a pincontrol driver for BCM6362
Add a pincotrol driver for BCM6362. BCM6362 allows muxing individual
GPIO pins to the LED controller, to be available by the integrated
wifi, or other functions. It also supports overlay groups, of which
only NAND is documented.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 7 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c | 692 ++++++++++++++++++++++++++++++
3 files changed, 700 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -23,3 +23,10 @@ config PINCTRL_BCM6358
select PINCTRL_BCM63XX
select GENERIC_PINCONF
select MFD_SYSCON
+
+config PINCTRL_BCM6362
+ bool "BCM6362 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
+obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
@@ -0,0 +1,692 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6362_NGPIO 48
+
+/* GPIO_BASEMODE register */
+#define BASEMODE_NAND BIT(2)
+
+enum bcm6362_pinctrl_reg {
+ BCM6362_LEDCTRL,
+ BCM6362_MODE,
+ BCM6362_CTRL,
+ BCM6362_BASEMODE,
+};
+
+struct bcm6362_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6362_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ enum bcm6362_pinctrl_reg reg;
+ u32 basemode_mask;
+};
+
+struct bcm6362_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *led;
+ void __iomem *mode;
+ void __iomem *ctrl;
+ void __iomem *basemode;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6362_PIN(a, b, mask) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(mask), \
+ }
+
+static const struct pinctrl_pin_desc bcm6362_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ BCM6362_PIN(8, "gpio8", BASEMODE_NAND),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ BCM6362_PIN(12, "gpio12", BASEMODE_NAND),
+ BCM6362_PIN(13, "gpio13", BASEMODE_NAND),
+ BCM6362_PIN(14, "gpio14", BASEMODE_NAND),
+ BCM6362_PIN(15, "gpio15", BASEMODE_NAND),
+ BCM6362_PIN(16, "gpio16", BASEMODE_NAND),
+ BCM6362_PIN(17, "gpio17", BASEMODE_NAND),
+ BCM6362_PIN(18, "gpio18", BASEMODE_NAND),
+ BCM6362_PIN(19, "gpio19", BASEMODE_NAND),
+ BCM6362_PIN(20, "gpio20", BASEMODE_NAND),
+ BCM6362_PIN(21, "gpio21", BASEMODE_NAND),
+ BCM6362_PIN(22, "gpio22", BASEMODE_NAND),
+ BCM6362_PIN(23, "gpio23", BASEMODE_NAND),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ BCM6362_PIN(27, "gpio27", BASEMODE_NAND),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned gpio32_pins[] = { 32 };
+static unsigned gpio33_pins[] = { 33 };
+static unsigned gpio34_pins[] = { 34 };
+static unsigned gpio35_pins[] = { 35 };
+static unsigned gpio36_pins[] = { 36 };
+static unsigned gpio37_pins[] = { 37 };
+static unsigned gpio38_pins[] = { 38 };
+static unsigned gpio39_pins[] = { 39 };
+static unsigned gpio40_pins[] = { 40 };
+static unsigned gpio41_pins[] = { 41 };
+static unsigned gpio42_pins[] = { 42 };
+static unsigned gpio43_pins[] = { 43 };
+static unsigned gpio44_pins[] = { 44 };
+static unsigned gpio45_pins[] = { 45 };
+static unsigned gpio46_pins[] = { 46 };
+static unsigned gpio47_pins[] = { 47 };
+
+static unsigned nand_grp_pins[] = {
+ 8, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 27,
+};
+
+#define BCM6362_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6362_pingroup bcm6362_groups[] = {
+ BCM6362_GROUP(gpio0),
+ BCM6362_GROUP(gpio1),
+ BCM6362_GROUP(gpio2),
+ BCM6362_GROUP(gpio3),
+ BCM6362_GROUP(gpio4),
+ BCM6362_GROUP(gpio5),
+ BCM6362_GROUP(gpio6),
+ BCM6362_GROUP(gpio7),
+ BCM6362_GROUP(gpio8),
+ BCM6362_GROUP(gpio9),
+ BCM6362_GROUP(gpio10),
+ BCM6362_GROUP(gpio11),
+ BCM6362_GROUP(gpio12),
+ BCM6362_GROUP(gpio13),
+ BCM6362_GROUP(gpio14),
+ BCM6362_GROUP(gpio15),
+ BCM6362_GROUP(gpio16),
+ BCM6362_GROUP(gpio17),
+ BCM6362_GROUP(gpio18),
+ BCM6362_GROUP(gpio19),
+ BCM6362_GROUP(gpio20),
+ BCM6362_GROUP(gpio21),
+ BCM6362_GROUP(gpio22),
+ BCM6362_GROUP(gpio23),
+ BCM6362_GROUP(gpio24),
+ BCM6362_GROUP(gpio25),
+ BCM6362_GROUP(gpio26),
+ BCM6362_GROUP(gpio27),
+ BCM6362_GROUP(gpio28),
+ BCM6362_GROUP(gpio29),
+ BCM6362_GROUP(gpio30),
+ BCM6362_GROUP(gpio31),
+ BCM6362_GROUP(gpio32),
+ BCM6362_GROUP(gpio33),
+ BCM6362_GROUP(gpio34),
+ BCM6362_GROUP(gpio35),
+ BCM6362_GROUP(gpio36),
+ BCM6362_GROUP(gpio37),
+ BCM6362_GROUP(gpio38),
+ BCM6362_GROUP(gpio39),
+ BCM6362_GROUP(gpio40),
+ BCM6362_GROUP(gpio41),
+ BCM6362_GROUP(gpio42),
+ BCM6362_GROUP(gpio43),
+ BCM6362_GROUP(gpio44),
+ BCM6362_GROUP(gpio45),
+ BCM6362_GROUP(gpio46),
+ BCM6362_GROUP(gpio47),
+ BCM6362_GROUP(nand_grp),
+};
+
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+static const char * const usb_device_led_groups[] = {
+ "gpio0",
+};
+
+static const char * const sys_irq_groups[] = {
+ "gpio1",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio2",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio3",
+};
+
+static const char * const robosw_led_data_groups[] = {
+ "gpio4",
+};
+
+static const char * const robosw_led_clk_groups[] = {
+ "gpio5",
+};
+
+static const char * const robosw_led0_groups[] = {
+ "gpio6",
+};
+
+static const char * const robosw_led1_groups[] = {
+ "gpio7",
+};
+
+static const char * const inet_led_groups[] = {
+ "gpio8",
+};
+
+static const char * const spi_cs2_groups[] = {
+ "gpio9",
+};
+
+static const char * const spi_cs3_groups[] = {
+ "gpio10",
+};
+
+static const char * const ntr_pulse_groups[] = {
+ "gpio11",
+};
+
+static const char * const uart1_scts_groups[] = {
+ "gpio12",
+};
+
+static const char * const uart1_srts_groups[] = {
+ "gpio13",
+};
+
+static const char * const uart1_sdin_groups[] = {
+ "gpio14",
+};
+
+static const char * const uart1_sdout_groups[] = {
+ "gpio15",
+};
+
+static const char * const adsl_spi_miso_groups[] = {
+ "gpio16",
+};
+
+static const char * const adsl_spi_mosi_groups[] = {
+ "gpio17",
+};
+
+static const char * const adsl_spi_clk_groups[] = {
+ "gpio18",
+};
+
+static const char * const adsl_spi_cs_groups[] = {
+ "gpio19",
+};
+
+static const char * const ephy0_led_groups[] = {
+ "gpio20",
+};
+
+static const char * const ephy1_led_groups[] = {
+ "gpio21",
+};
+
+static const char * const ephy2_led_groups[] = {
+ "gpio22",
+};
+
+static const char * const ephy3_led_groups[] = {
+ "gpio23",
+};
+
+static const char * const ext_irq0_groups[] = {
+ "gpio24",
+};
+
+static const char * const ext_irq1_groups[] = {
+ "gpio25",
+};
+
+static const char * const ext_irq2_groups[] = {
+ "gpio26",
+};
+
+static const char * const ext_irq3_groups[] = {
+ "gpio27",
+};
+
+static const char * const wifi_groups[] = {
+ "gpio32",
+ "gpio33",
+ "gpio34",
+ "gpio35",
+ "gpio36",
+ "gpio37",
+ "gpio38",
+ "gpio39",
+ "gpio40",
+ "gpio41",
+ "gpio42",
+ "gpio43",
+ "gpio44",
+ "gpio45",
+ "gpio46",
+ "gpio47",
+};
+
+static const char * const nand_groups[] = {
+ "nand_grp",
+};
+
+#define BCM6362_LED_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_LEDCTRL, \
+ }
+
+#define BCM6362_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_MODE, \
+ }
+
+#define BCM6362_CTRL_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_CTRL, \
+ }
+
+#define BCM6362_BASEMODE_FUN(n, mask) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_BASEMODE, \
+ .basemode_mask = (mask), \
+ }
+
+static const struct bcm6362_function bcm6362_funcs[] = {
+ BCM6362_LED_FUN(led),
+ BCM6362_MODE_FUN(usb_device_led),
+ BCM6362_MODE_FUN(sys_irq),
+ BCM6362_MODE_FUN(serial_led_clk),
+ BCM6362_MODE_FUN(serial_led_data),
+ BCM6362_MODE_FUN(robosw_led_data),
+ BCM6362_MODE_FUN(robosw_led_clk),
+ BCM6362_MODE_FUN(robosw_led0),
+ BCM6362_MODE_FUN(robosw_led1),
+ BCM6362_MODE_FUN(inet_led),
+ BCM6362_MODE_FUN(spi_cs2),
+ BCM6362_MODE_FUN(spi_cs3),
+ BCM6362_MODE_FUN(ntr_pulse),
+ BCM6362_MODE_FUN(uart1_scts),
+ BCM6362_MODE_FUN(uart1_srts),
+ BCM6362_MODE_FUN(uart1_sdin),
+ BCM6362_MODE_FUN(uart1_sdout),
+ BCM6362_MODE_FUN(adsl_spi_miso),
+ BCM6362_MODE_FUN(adsl_spi_mosi),
+ BCM6362_MODE_FUN(adsl_spi_clk),
+ BCM6362_MODE_FUN(adsl_spi_cs),
+ BCM6362_MODE_FUN(ephy0_led),
+ BCM6362_MODE_FUN(ephy1_led),
+ BCM6362_MODE_FUN(ephy2_led),
+ BCM6362_MODE_FUN(ephy3_led),
+ BCM6362_MODE_FUN(ext_irq0),
+ BCM6362_MODE_FUN(ext_irq1),
+ BCM6362_MODE_FUN(ext_irq2),
+ BCM6362_MODE_FUN(ext_irq3),
+ BCM6362_CTRL_FUN(wifi),
+ BCM6362_BASEMODE_FUN(nand, BASEMODE_NAND),
+};
+
+static int bcm6362_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6362_groups);
+}
+
+static const char *bcm6362_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6362_groups[group].name;
+}
+
+static int bcm6362_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6362_groups[group].pins;
+ *num_pins = bcm6362_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6362_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6362_funcs);
+}
+
+static const char *bcm6362_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6362_funcs[selector].name;
+}
+
+static int bcm6362_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6362_funcs[selector].groups;
+ *num_groups = bcm6362_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6362_rmw_mux(struct bcm6362_pinctrl *pctl, void __iomem *reg,
+ u32 mask, u32 val)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ tmp = __raw_readl(reg);
+ tmp &= ~mask;
+ tmp |= val & mask;
+ __raw_writel(tmp, reg);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static void bcm6362_set_gpio(struct bcm6362_pinctrl *pctl, unsigned pin)
+{
+ const struct pinctrl_pin_desc *desc = &bcm6362_pins[pin];
+ u32 mask = BIT(pin % 32);
+
+ if (desc->drv_data)
+ bcm6362_rmw_mux(pctl, pctl->basemode, (u32)desc->drv_data, 0);
+
+ if (pin < 32) {
+ /* base mode 0 => gpio 1 => mux function */
+ bcm6362_rmw_mux(pctl, pctl->mode, mask, 0);
+
+ /* pins 0-23 might be muxed to led */
+ if (pin < 24)
+ bcm6362_rmw_mux(pctl, pctl->led, mask, 0);
+ } else {
+ /* ctrl reg 0 => wifi function 1 => gpio */
+ bcm6362_rmw_mux(pctl, pctl->ctrl, mask, mask);
+ }
+}
+
+static int bcm6362_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6362_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6362_pingroup *grp = &bcm6362_groups[group];
+ const struct bcm6362_function *f = &bcm6362_funcs[selector];
+ unsigned i;
+ void __iomem *reg;
+ u32 val, mask;
+
+ for (i = 0; i < grp->num_pins; i++)
+ bcm6362_set_gpio(pctl, grp->pins[i]);
+
+ switch (f->reg) {
+ case BCM6362_LEDCTRL:
+ reg = pctl->led;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM6362_MODE:
+ reg = pctl->ctrl;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM6362_CTRL:
+ reg = pctl->ctrl;
+ mask = BIT(grp->pins[0]);
+ val = 0;
+ break;
+ case BCM6362_BASEMODE:
+ reg = pctl->basemode;
+ mask = f->basemode_mask;
+ val = f->basemode_mask;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ bcm6362_rmw_mux(pctl, reg, mask, val);
+
+ return 0;
+}
+
+static int bcm6362_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6362_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ bcm6362_set_gpio(pctl, offset);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6362_pctl_ops = {
+ .get_groups_count = bcm6362_pinctrl_get_group_count,
+ .get_group_name = bcm6362_pinctrl_get_group_name,
+ .get_group_pins = bcm6362_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6362_pmx_ops = {
+ .get_functions_count = bcm6362_pinctrl_get_func_count,
+ .get_function_name = bcm6362_pinctrl_get_func_name,
+ .get_function_groups = bcm6362_pinctrl_get_groups,
+ .set_mux = bcm6362_pinctrl_set_mux,
+ .gpio_request_enable = bcm6362_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6362_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6362_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *led, *mode, *ctrl, *basemode;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "led");
+ led = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(led))
+ return PTR_ERR(led);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
+ ctrl = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "basemode");
+ basemode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(basemode))
+ return PTR_ERR(basemode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->led = led;
+ pctl->mode = mode;
+ pctl->ctrl = ctrl;
+ pctl->basemode = basemode;
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6362_pctl_ops;
+ pctl->desc.pmxops = &bcm6362_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6362_pins);
+ pctl->desc.pins = bcm6362_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6362_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6362_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6362-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6362_pinctrl_driver = {
+ .probe = bcm6362_pinctrl_probe,
+ .driver = {
+ .name = "bcm6362-pinctrl",
+ .of_match_table = bcm6362_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6362_pinctrl_driver);

View file

@ -1,84 +0,0 @@
From 30594cf9bfff176a9e4b14c50dcd8b9d0cc3edec Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:36:51 +0200
Subject: [PATCH 10/16] Documentation: add BCM6368 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6368 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6368-pinctrl.txt | 67 ++++++++++++++++++++++
1 file changed, 67 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.txt
@@ -0,0 +1,67 @@
+* Broadcom BCM6368 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6368-pinctrl".
+- reg: Register specifiers of dirout, dat, mode registers.
+- reg-names: Must be "dirout", "dat", "mode".
+- brcm,gpiobasemode: Phandle to the gpio basemode register.
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6368-pinctrl";
+ reg = <0x10000080 0x08>,
+ <0x10000088 0x08>,
+ <0x10000098 0x04>;
+ reg-names = "dirout", "dat", "mode";
+ brcm,gpiobasemode = <&gpiobasemode>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+gpiobasemode: syscon@100000b8 {
+ compatible = "brcm,bcm6368-gpiobasemode", "syscon";
+ reg = <0x100000b8 4>;
+ native-endian;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 analog_afe0
+gpio1 1 analog_afe1
+gpio2 2 sys_irq
+gpio3 3 serial_led_data
+gpio4 4 serial_led_clk
+gpio5 5 inet_led
+gpio6 6 ephy0_led
+gpio7 7 ephy1_led
+gpio8 8 ephy2_led
+gpio9 9 ephy3_led
+gpio10 10 robosw_led_data
+gpio11 11 robosw_led_clk
+gpio12 12 robosw_led0
+gpio13 13 robosw_led1
+gpio14 14 usb_device_led
+gpio15 15 -
+gpio16 16 pci_req1
+gpio17 17 pci_gnt1
+gpio18 18 pci_intb
+gpio19 19 pci_req0
+gpio20 20 pci_gnt0
+gpio21 21 -
+gpio22 22 pcmcia_cd1
+gpio23 23 pcmcia_cd2
+gpio24 24 pcmcia_vs1
+gpio25 25 pcmcia_vs2
+gpio26 26 ebi_cs2
+gpio27 27 ebi_cs3
+gpio28 28 spi_cs2
+gpio29 29 spi_cs3
+gpio30 30 spi_cs4
+gpio31 31 spi_cs5
+uart1_grp 30-33 uart1

View file

@ -1,620 +0,0 @@
From 90be3cb4f1a45b8be4a4ec264cd66c2f8e893fcb Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:18:25 +0200
Subject: [PATCH 11/16] pinctrl: add a pincontrol driver for BCM6368
Add a pincontrol driver for BCM6368. BCM6368 allows muxing the first 32
GPIOs onto alternative functions. Not all are documented.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 15 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c | 573 ++++++++++++++++++++++++++++++
3 files changed, 589 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -30,3 +30,18 @@ config PINCTRL_BCM6362
select PINCONF
select PINCTRL_BCM63XX
select GENERIC_PINCONF
+
+config PINCTRL_BCM6368
+ bool "BCM6368 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
+ select MFD_SYSCON
+
+config PINCTRL_BCM63268
+ bool "BCM63268 pincontrol driver" if COMPILE_TEST
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl
obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
+obj-$(CONFIG_PINCTRL_BCM6368) += pinctrl-bcm6368.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c
@@ -0,0 +1,573 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6368_NGPIO 38
+
+#define BCM6368_BASEMODE_MASK 0x7
+#define BCM6368_BASEMODE_GPIO 0x0
+#define BCM6368_BASEMODE_UART1 0x1
+
+struct bcm6368_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6368_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ unsigned dir_out:16;
+ unsigned basemode:3;
+};
+
+struct bcm6368_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *mode;
+ struct regmap_field *overlay;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6368_BASEMODE_PIN(a, b) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)true \
+ }
+
+static const struct pinctrl_pin_desc bcm6368_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ BCM6368_BASEMODE_PIN(30, "gpio30"),
+ BCM6368_BASEMODE_PIN(31, "gpio31"),
+ BCM6368_BASEMODE_PIN(32, "gpio32"),
+ BCM6368_BASEMODE_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned uart1_grp_pins[] = { 30, 31, 32, 33 };
+
+#define BCM6368_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6368_pingroup bcm6368_groups[] = {
+ BCM6368_GROUP(gpio0),
+ BCM6368_GROUP(gpio1),
+ BCM6368_GROUP(gpio2),
+ BCM6368_GROUP(gpio3),
+ BCM6368_GROUP(gpio4),
+ BCM6368_GROUP(gpio5),
+ BCM6368_GROUP(gpio6),
+ BCM6368_GROUP(gpio7),
+ BCM6368_GROUP(gpio8),
+ BCM6368_GROUP(gpio9),
+ BCM6368_GROUP(gpio10),
+ BCM6368_GROUP(gpio11),
+ BCM6368_GROUP(gpio12),
+ BCM6368_GROUP(gpio13),
+ BCM6368_GROUP(gpio14),
+ BCM6368_GROUP(gpio15),
+ BCM6368_GROUP(gpio16),
+ BCM6368_GROUP(gpio17),
+ BCM6368_GROUP(gpio18),
+ BCM6368_GROUP(gpio19),
+ BCM6368_GROUP(gpio20),
+ BCM6368_GROUP(gpio21),
+ BCM6368_GROUP(gpio22),
+ BCM6368_GROUP(gpio23),
+ BCM6368_GROUP(gpio24),
+ BCM6368_GROUP(gpio25),
+ BCM6368_GROUP(gpio26),
+ BCM6368_GROUP(gpio27),
+ BCM6368_GROUP(gpio28),
+ BCM6368_GROUP(gpio29),
+ BCM6368_GROUP(gpio30),
+ BCM6368_GROUP(gpio31),
+ BCM6368_GROUP(uart1_grp),
+};
+
+static const char * const analog_afe_0_groups[] = {
+ "gpio0",
+};
+
+static const char * const analog_afe_1_groups[] = {
+ "gpio1",
+};
+
+static const char * const sys_irq_groups[] = {
+ "gpio2",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio3",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio4",
+};
+
+static const char * const inet_led_groups[] = {
+ "gpio5",
+};
+
+static const char * const ephy0_led_groups[] = {
+ "gpio6",
+};
+
+static const char * const ephy1_led_groups[] = {
+ "gpio7",
+};
+
+static const char * const ephy2_led_groups[] = {
+ "gpio8",
+};
+
+static const char * const ephy3_led_groups[] = {
+ "gpio9",
+};
+
+static const char * const robosw_led_data_groups[] = {
+ "gpio10",
+};
+
+static const char * const robosw_led_clk_groups[] = {
+ "gpio11",
+};
+
+static const char * const robosw_led0_groups[] = {
+ "gpio12",
+};
+
+static const char * const robosw_led1_groups[] = {
+ "gpio13",
+};
+
+static const char * const usb_device_led_groups[] = {
+ "gpio14",
+};
+
+static const char * const pci_req1_groups[] = {
+ "gpio16",
+};
+
+static const char * const pci_gnt1_groups[] = {
+ "gpio17",
+};
+
+static const char * const pci_intb_groups[] = {
+ "gpio18",
+};
+
+static const char * const pci_req0_groups[] = {
+ "gpio19",
+};
+
+static const char * const pci_gnt0_groups[] = {
+ "gpio20",
+};
+
+static const char * const pcmcia_cd1_groups[] = {
+ "gpio22",
+};
+
+static const char * const pcmcia_cd2_groups[] = {
+ "gpio23",
+};
+
+static const char * const pcmcia_vs1_groups[] = {
+ "gpio24",
+};
+
+static const char * const pcmcia_vs2_groups[] = {
+ "gpio25",
+};
+
+static const char * const ebi_cs2_groups[] = {
+ "gpio26",
+};
+
+static const char * const ebi_cs3_groups[] = {
+ "gpio27",
+};
+
+static const char * const spi_cs2_groups[] = {
+ "gpio28",
+};
+
+static const char * const spi_cs3_groups[] = {
+ "gpio29",
+};
+
+static const char * const spi_cs4_groups[] = {
+ "gpio30",
+};
+
+static const char * const spi_cs5_groups[] = {
+ "gpio31",
+};
+
+static const char * const uart1_groups[] = {
+ "uart1_grp",
+};
+
+#define BCM6368_FUN(n, out) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .dir_out = out, \
+ }
+
+#define BCM6368_BASEMODE_FUN(n, val, out) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .basemode = BCM6368_BASEMODE_##val, \
+ .dir_out = out, \
+ }
+
+static const struct bcm6368_function bcm6368_funcs[] = {
+ BCM6368_FUN(analog_afe_0, 1),
+ BCM6368_FUN(analog_afe_1, 1),
+ BCM6368_FUN(sys_irq, 1),
+ BCM6368_FUN(serial_led_data, 1),
+ BCM6368_FUN(serial_led_clk, 1),
+ BCM6368_FUN(inet_led, 1),
+ BCM6368_FUN(ephy0_led, 1),
+ BCM6368_FUN(ephy1_led, 1),
+ BCM6368_FUN(ephy2_led, 1),
+ BCM6368_FUN(ephy3_led, 1),
+ BCM6368_FUN(robosw_led_data, 1),
+ BCM6368_FUN(robosw_led_clk, 1),
+ BCM6368_FUN(robosw_led0, 1),
+ BCM6368_FUN(robosw_led1, 1),
+ BCM6368_FUN(usb_device_led, 1),
+ BCM6368_FUN(pci_req1, 0),
+ BCM6368_FUN(pci_gnt1, 0),
+ BCM6368_FUN(pci_intb, 0),
+ BCM6368_FUN(pci_req0, 0),
+ BCM6368_FUN(pci_gnt0, 0),
+ BCM6368_FUN(pcmcia_cd1, 0),
+ BCM6368_FUN(pcmcia_cd2, 0),
+ BCM6368_FUN(pcmcia_vs1, 0),
+ BCM6368_FUN(pcmcia_vs2, 0),
+ BCM6368_FUN(ebi_cs2, 1),
+ BCM6368_FUN(ebi_cs3, 1),
+ BCM6368_FUN(spi_cs2, 1),
+ BCM6368_FUN(spi_cs3, 1),
+ BCM6368_FUN(spi_cs4, 1),
+ BCM6368_FUN(spi_cs5, 1),
+ BCM6368_BASEMODE_FUN(uart1, UART1, 0x6),
+};
+
+static int bcm6368_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6368_groups);
+}
+
+static const char *bcm6368_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6368_groups[group].name;
+}
+
+static int bcm6368_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6368_groups[group].pins;
+ *num_pins = bcm6368_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6368_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6368_funcs);
+}
+
+static const char *bcm6368_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6368_funcs[selector].name;
+}
+
+static int bcm6368_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6368_funcs[selector].groups;
+ *num_groups = bcm6368_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6368_rmw_mux(struct bcm6368_pinctrl *pctl, void __iomem *reg,
+ u32 mask, u32 val)
+{
+ u32 tmp;
+
+ tmp = __raw_readl(reg);
+ tmp &= ~mask;
+ tmp |= (val & mask);
+ __raw_writel(tmp, reg);
+}
+
+static int bcm6368_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6368_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6368_pingroup *grp = &bcm6368_groups[group];
+ const struct bcm6368_function *fun = &bcm6368_funcs[selector];
+ unsigned long flags;
+ int i, pin;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ if (fun->basemode) {
+ u32 mask = 0;
+
+ for (i = 0; i < grp->num_pins; i++) {
+ pin = grp->pins[i];
+ if (pin < 32)
+ mask |= BIT(pin);
+ }
+
+ bcm6368_rmw_mux(pctl, pctl->mode, mask, 0);
+ regmap_field_write(pctl->overlay, fun->basemode);
+ } else {
+ pin = grp->pins[0];
+
+ if (bcm6368_pins[pin].drv_data)
+ regmap_field_write(pctl->overlay,
+ BCM6368_BASEMODE_GPIO);
+
+ bcm6368_rmw_mux(pctl, pctl->mode, BIT(pin), BIT(pin));
+ }
+ spin_unlock_irqrestore(&pctl->lock, flags);
+
+ for (pin = 0; pin < grp->num_pins; pin++) {
+ int hw_gpio = bcm6368_pins[pin].number;
+ struct gpio_chip *gc = &pctl->gpio[hw_gpio / 32];
+
+ if (fun->dir_out & BIT(pin))
+ gc->direction_output(gc, hw_gpio % 32, 0);
+ else
+ gc->direction_input(gc, hw_gpio % 32);
+ }
+
+ return 0;
+}
+
+static int bcm6368_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6368_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned long flags;
+
+ if (offset >= 32 && !bcm6368_pins[offset].drv_data)
+ return 0;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ /* disable all functions using this pin */
+ if (offset < 32)
+ bcm6368_rmw_mux(pctl, pctl->mode, BIT(offset), 0);
+
+ if (bcm6368_pins[offset].drv_data)
+ regmap_field_write(pctl->overlay, BCM6368_BASEMODE_GPIO);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6368_pctl_ops = {
+ .get_groups_count = bcm6368_pinctrl_get_group_count,
+ .get_group_name = bcm6368_pinctrl_get_group_name,
+ .get_group_pins = bcm6368_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6368_pmx_ops = {
+ .get_functions_count = bcm6368_pinctrl_get_func_count,
+ .get_function_name = bcm6368_pinctrl_get_func_name,
+ .get_function_groups = bcm6368_pinctrl_get_groups,
+ .set_mux = bcm6368_pinctrl_set_mux,
+ .gpio_request_enable = bcm6368_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6368_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6368_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *mode;
+ struct regmap *basemode;
+ struct reg_field overlay = REG_FIELD(0, 0, 3);
+
+ if (pdev->dev.of_node)
+ basemode = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "brcm,gpiobasemode");
+ else
+ basemode = syscon_regmap_lookup_by_pdevname("syscon.b00000b8");
+
+ if (IS_ERR(basemode))
+ return PTR_ERR(basemode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ pctl->overlay = devm_regmap_field_alloc(&pdev->dev, basemode, overlay);
+ if (IS_ERR(pctl->overlay))
+ return PTR_ERR(pctl->overlay);
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->mode = mode;
+
+ /* disable all muxes by default */
+ __raw_writel(0, pctl->mode);
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6368_pctl_ops;
+ pctl->desc.pmxops = &bcm6368_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6368_pins);
+ pctl->desc.pins = bcm6368_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6368_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6368_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6368-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6368_pinctrl_driver = {
+ .probe = bcm6368_pinctrl_probe,
+ .driver = {
+ .name = "bcm6368-pinctrl",
+ .of_match_table = bcm6368_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6368_pinctrl_driver);

View file

@ -1,106 +0,0 @@
From 28cc80e4ada5d73d5305fd268297825cd8d01936 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:37:08 +0200
Subject: [PATCH 12/16] Documentation: add BCM63268 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in the BCM63268
family SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm63268-pinctrl.txt | 88 ++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.txt
@@ -0,0 +1,88 @@
+* Broadcom BCM63268 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6362-pinctrl".
+- reg: Register specifiers of dirout, dat, led, mode, ctrl, basemode registers.
+- reg-names: Must be "dirout", "dat", "led", "mode", "ctrl", "basemode".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@100000c0 {
+ compatible = "brcm,bcm63268-pinctrl";
+ reg = <0x100000c0 0x8>,
+ <0x100000c8 0x8>,
+ <0x100000d0 0x4>,
+ <0x100000d8 0x4>,
+ <0x100000dc 0x4>,
+ <0x100000f8 0x4>;
+ reg-names = "dirout", "dat", "led", "mode",
+ "ctrl", "basemode";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led, serial_led_clk
+gpio1 1 led, serial_led_data
+gpio2 2 led,
+gpio3 3 led,
+gpio4 4 led,
+gpio5 5 led,
+gpio6 6 led,
+gpio7 7 led,
+gpio8 8 led, hsspi_cs6
+gpio9 9 led, hsspi_cs7
+gpio10 10 led, uart1_scts
+gpio11 11 led, uart1_srts
+gpio12 12 led, uart1_sdin
+gpio13 13 led, uart1_sdout
+gpio14 14 led, ntr_pulse_in
+gpio15 15 led, dsl_ntr_pulse_out
+gpio16 16 led, hsspi_cs4
+gpio17 17 led, hsspi_cs5
+gpio18 18 led, adsl_spi_miso
+gpio19 19 led, adsl_spi_mosi
+gpio20 20 led,
+gpio21 21 led,
+gpio22 22 led, vreg_clk
+gpio23 23 led, pcie_clkreq_b
+gpio24 24 uart1_scts
+gpio25 25 uart1_srts
+gpio26 26 uart1_sdin
+gpio27 27 uart1_sdout
+gpio28 28 ntr_pulse_in
+gpio29 29 dsl_ntr_pulse_out
+gpio30 30 switch_led_clk
+gpio31 31 switch_led_data
+gpio32 32 wifi
+gpio33 33 wifi
+gpio34 34 wifi
+gpio35 35 wifi
+gpio36 36 wifi
+gpio37 37 wifi
+gpio38 38 wifi
+gpio39 39 wifi
+gpio40 40 wifi
+gpio41 41 wifi
+gpio42 42 wifi
+gpio43 43 wifi
+gpio44 44 wifi
+gpio45 45 wifi
+gpio46 46 wifi
+gpio47 47 wifi
+gpio48 48 wifi
+gpio49 49 wifi
+gpio50 50 wifi
+gpio51 51 wifi
+nand_grp 2-7,24-31 nand
+dect_pd_grp 8-9 dect_pd
+vdsl_phy0_grp 10-11 vdsl_phy0
+vdsl_phy1_grp 12-13 vdsl_phy1
+vdsl_phy2_grp 24-25 vdsl_phy2
+vdsl_phy3_grp 26-27 vdsl_phy3

View file

@ -1,736 +0,0 @@
From 8665d3ea63649cc155286c75f83f694a930580e5 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:19:12 +0200
Subject: [PATCH 13/16] pinctrl: add a pincontrol driver for BCM63268
Add a pincontrol driver for BCM63268. BCM63268 allows muxing GPIOs
to different functions. Depending on the mux, these are either single
pin configurations or whole pin groups.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c | 710 +++++++++++++++++++++++++++++
2 files changed, 711 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
obj-$(CONFIG_PINCTRL_BCM6368) += pinctrl-bcm6368.o
+obj-$(CONFIG_PINCTRL_BCM63268) += pinctrl-bcm63268.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c
@@ -0,0 +1,710 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM63268_NGPIO 52
+
+/* GPIO_BASEMODE register */
+#define BASEMODE_NAND BIT(2) /* GPIOs 2-7, 24-31 */
+#define BASEMODE_GPIO35 BIT(4) /* GPIO 35 */
+#define BASEMODE_DECTPD BIT(5) /* GPIOs 8/9 */
+#define BASEMODE_VDSL_PHY_0 BIT(6) /* GPIOs 10/11 */
+#define BASEMODE_VDSL_PHY_1 BIT(7) /* GPIOs 12/13 */
+#define BASEMODE_VDSL_PHY_2 BIT(8) /* GPIOs 24/25 */
+#define BASEMODE_VDSL_PHY_3 BIT(9) /* GPIOs 26/27 */
+
+enum bcm63268_pinctrl_reg {
+ BCM63268_LEDCTRL,
+ BCM63268_MODE,
+ BCM63268_CTRL,
+ BCM63268_BASEMODE,
+};
+
+struct bcm63268_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm63268_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ enum bcm63268_pinctrl_reg reg;
+ u32 mask;
+};
+
+struct bcm63268_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *led;
+ void __iomem *mode;
+ void __iomem *ctrl;
+ void __iomem *basemode;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM63268_PIN(a, b, basemode) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(basemode) \
+ }
+
+static const struct pinctrl_pin_desc bcm63268_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ BCM63268_PIN(2, "gpio2", BASEMODE_NAND),
+ BCM63268_PIN(3, "gpio3", BASEMODE_NAND),
+ BCM63268_PIN(4, "gpio4", BASEMODE_NAND),
+ BCM63268_PIN(5, "gpio5", BASEMODE_NAND),
+ BCM63268_PIN(6, "gpio6", BASEMODE_NAND),
+ BCM63268_PIN(7, "gpio7", BASEMODE_NAND),
+ BCM63268_PIN(8, "gpio8", BASEMODE_DECTPD),
+ BCM63268_PIN(9, "gpio9", BASEMODE_DECTPD),
+ BCM63268_PIN(10, "gpio10", BASEMODE_VDSL_PHY_0),
+ BCM63268_PIN(11, "gpio11", BASEMODE_VDSL_PHY_0),
+ BCM63268_PIN(12, "gpio12", BASEMODE_VDSL_PHY_1),
+ BCM63268_PIN(13, "gpio13", BASEMODE_VDSL_PHY_1),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ BCM63268_PIN(24, "gpio24", BASEMODE_NAND | BASEMODE_VDSL_PHY_2),
+ BCM63268_PIN(25, "gpio25", BASEMODE_NAND | BASEMODE_VDSL_PHY_2),
+ BCM63268_PIN(26, "gpio26", BASEMODE_NAND | BASEMODE_VDSL_PHY_3),
+ BCM63268_PIN(27, "gpio27", BASEMODE_NAND | BASEMODE_VDSL_PHY_3),
+ BCM63268_PIN(28, "gpio28", BASEMODE_NAND),
+ BCM63268_PIN(29, "gpio29", BASEMODE_NAND),
+ BCM63268_PIN(30, "gpio30", BASEMODE_NAND),
+ BCM63268_PIN(31, "gpio31", BASEMODE_NAND),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+ PINCTRL_PIN(48, "gpio48"),
+ PINCTRL_PIN(49, "gpio49"),
+ PINCTRL_PIN(50, "gpio50"),
+ PINCTRL_PIN(51, "gpio51"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned gpio32_pins[] = { 32 };
+static unsigned gpio33_pins[] = { 33 };
+static unsigned gpio34_pins[] = { 34 };
+static unsigned gpio35_pins[] = { 35 };
+static unsigned gpio36_pins[] = { 36 };
+static unsigned gpio37_pins[] = { 37 };
+static unsigned gpio38_pins[] = { 38 };
+static unsigned gpio39_pins[] = { 39 };
+static unsigned gpio40_pins[] = { 40 };
+static unsigned gpio41_pins[] = { 41 };
+static unsigned gpio42_pins[] = { 42 };
+static unsigned gpio43_pins[] = { 43 };
+static unsigned gpio44_pins[] = { 44 };
+static unsigned gpio45_pins[] = { 45 };
+static unsigned gpio46_pins[] = { 46 };
+static unsigned gpio47_pins[] = { 47 };
+static unsigned gpio48_pins[] = { 48 };
+static unsigned gpio49_pins[] = { 49 };
+static unsigned gpio50_pins[] = { 50 };
+static unsigned gpio51_pins[] = { 51 };
+
+static unsigned nand_grp_pins[] = {
+ 2, 3, 4, 5, 6, 7, 24,
+ 25, 26, 27, 28, 29, 30, 31,
+};
+
+static unsigned dectpd_grp_pins[] = { 8, 9 };
+static unsigned vdsl_phy0_grp_pins[] = { 10, 11 };
+static unsigned vdsl_phy1_grp_pins[] = { 12, 13 };
+static unsigned vdsl_phy2_grp_pins[] = { 24, 25 };
+static unsigned vdsl_phy3_grp_pins[] = { 26, 27 };
+
+#define BCM63268_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm63268_pingroup bcm63268_groups[] = {
+ BCM63268_GROUP(gpio0),
+ BCM63268_GROUP(gpio1),
+ BCM63268_GROUP(gpio2),
+ BCM63268_GROUP(gpio3),
+ BCM63268_GROUP(gpio4),
+ BCM63268_GROUP(gpio5),
+ BCM63268_GROUP(gpio6),
+ BCM63268_GROUP(gpio7),
+ BCM63268_GROUP(gpio8),
+ BCM63268_GROUP(gpio9),
+ BCM63268_GROUP(gpio10),
+ BCM63268_GROUP(gpio11),
+ BCM63268_GROUP(gpio12),
+ BCM63268_GROUP(gpio13),
+ BCM63268_GROUP(gpio14),
+ BCM63268_GROUP(gpio15),
+ BCM63268_GROUP(gpio16),
+ BCM63268_GROUP(gpio17),
+ BCM63268_GROUP(gpio18),
+ BCM63268_GROUP(gpio19),
+ BCM63268_GROUP(gpio20),
+ BCM63268_GROUP(gpio21),
+ BCM63268_GROUP(gpio22),
+ BCM63268_GROUP(gpio23),
+ BCM63268_GROUP(gpio24),
+ BCM63268_GROUP(gpio25),
+ BCM63268_GROUP(gpio26),
+ BCM63268_GROUP(gpio27),
+ BCM63268_GROUP(gpio28),
+ BCM63268_GROUP(gpio29),
+ BCM63268_GROUP(gpio30),
+ BCM63268_GROUP(gpio31),
+ BCM63268_GROUP(gpio32),
+ BCM63268_GROUP(gpio33),
+ BCM63268_GROUP(gpio34),
+ BCM63268_GROUP(gpio35),
+ BCM63268_GROUP(gpio36),
+ BCM63268_GROUP(gpio37),
+ BCM63268_GROUP(gpio38),
+ BCM63268_GROUP(gpio39),
+ BCM63268_GROUP(gpio40),
+ BCM63268_GROUP(gpio41),
+ BCM63268_GROUP(gpio42),
+ BCM63268_GROUP(gpio43),
+ BCM63268_GROUP(gpio44),
+ BCM63268_GROUP(gpio45),
+ BCM63268_GROUP(gpio46),
+ BCM63268_GROUP(gpio47),
+ BCM63268_GROUP(gpio48),
+ BCM63268_GROUP(gpio49),
+ BCM63268_GROUP(gpio50),
+ BCM63268_GROUP(gpio51),
+
+ /* multi pin groups */
+ BCM63268_GROUP(nand_grp),
+ BCM63268_GROUP(dectpd_grp),
+ BCM63268_GROUP(vdsl_phy0_grp),
+ BCM63268_GROUP(vdsl_phy1_grp),
+ BCM63268_GROUP(vdsl_phy2_grp),
+ BCM63268_GROUP(vdsl_phy3_grp),
+};
+
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio0",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio1",
+};
+
+static const char * const hsspi_cs4_groups[] = {
+ "gpio16",
+};
+
+static const char * const hsspi_cs5_groups[] = {
+ "gpio17",
+};
+
+static const char * const hsspi_cs6_groups[] = {
+ "gpio8",
+};
+
+static const char * const hsspi_cs7_groups[] = {
+ "gpio9",
+};
+
+static const char * const uart1_scts_groups[] = {
+ "gpio10",
+ "gpio24",
+};
+
+static const char * const uart1_srts_groups[] = {
+ "gpio11",
+ "gpio25",
+};
+
+static const char * const uart1_sdin_groups[] = {
+ "gpio12",
+ "gpio26",
+};
+
+static const char * const uart1_sdout_groups[] = {
+ "gpio13",
+ "gpio27",
+};
+
+static const char * const ntr_pulse_in_groups[] = {
+ "gpio14",
+ "gpio28",
+};
+
+static const char * const dsl_ntr_pulse_out_groups[] = {
+ "gpio15",
+ "gpio29",
+};
+
+static const char * const adsl_spi_miso_groups[] = {
+ "gpio18",
+};
+
+static const char * const adsl_spi_mosi_groups[] = {
+ "gpio19",
+};
+
+static const char * const vreg_clk_groups[] = {
+ "gpio22",
+};
+
+static const char * const pcie_clkreq_b_groups[] = {
+ "gpio23",
+};
+
+static const char * const switch_led_clk_groups[] = {
+ "gpio30",
+};
+
+static const char * const switch_led_data_groups[] = {
+ "gpio31",
+};
+
+static const char * const wifi_groups[] = {
+ "gpio32",
+ "gpio33",
+ "gpio34",
+ "gpio35",
+ "gpio36",
+ "gpio37",
+ "gpio38",
+ "gpio39",
+ "gpio40",
+ "gpio41",
+ "gpio42",
+ "gpio43",
+ "gpio44",
+ "gpio45",
+ "gpio46",
+ "gpio47",
+ "gpio48",
+ "gpio49",
+ "gpio50",
+ "gpio51",
+};
+
+static const char * const nand_groups[] = {
+ "nand_grp",
+};
+
+static const char * const dectpd_groups[] = {
+ "dectpd_grp",
+};
+
+static const char * const vdsl_phy_override_0_groups[] = {
+ "vdsl_phy_override_0_grp",
+};
+
+static const char * const vdsl_phy_override_1_groups[] = {
+ "vdsl_phy_override_1_grp",
+};
+
+static const char * const vdsl_phy_override_2_groups[] = {
+ "vdsl_phy_override_2_grp",
+};
+
+static const char * const vdsl_phy_override_3_groups[] = {
+ "vdsl_phy_override_3_grp",
+};
+
+#define BCM63268_LED_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_LEDCTRL, \
+ }
+
+#define BCM63268_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_MODE, \
+ }
+
+#define BCM63268_CTRL_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_CTRL, \
+ }
+
+#define BCM63268_BASEMODE_FUN(n, val) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_BASEMODE, \
+ .mask = val, \
+ }
+
+static const struct bcm63268_function bcm63268_funcs[] = {
+ BCM63268_LED_FUN(led),
+ BCM63268_MODE_FUN(serial_led_clk),
+ BCM63268_MODE_FUN(serial_led_data),
+ BCM63268_MODE_FUN(hsspi_cs6),
+ BCM63268_MODE_FUN(hsspi_cs7),
+ BCM63268_MODE_FUN(uart1_scts),
+ BCM63268_MODE_FUN(uart1_srts),
+ BCM63268_MODE_FUN(uart1_sdin),
+ BCM63268_MODE_FUN(uart1_sdout),
+ BCM63268_MODE_FUN(ntr_pulse_in),
+ BCM63268_MODE_FUN(dsl_ntr_pulse_out),
+ BCM63268_MODE_FUN(hsspi_cs4),
+ BCM63268_MODE_FUN(hsspi_cs5),
+ BCM63268_MODE_FUN(adsl_spi_miso),
+ BCM63268_MODE_FUN(adsl_spi_mosi),
+ BCM63268_MODE_FUN(vreg_clk),
+ BCM63268_MODE_FUN(pcie_clkreq_b),
+ BCM63268_MODE_FUN(switch_led_clk),
+ BCM63268_MODE_FUN(switch_led_data),
+ BCM63268_CTRL_FUN(wifi),
+ BCM63268_BASEMODE_FUN(nand, BASEMODE_NAND),
+ BCM63268_BASEMODE_FUN(dectpd, BASEMODE_DECTPD),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_0, BASEMODE_VDSL_PHY_0),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_1, BASEMODE_VDSL_PHY_1),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_2, BASEMODE_VDSL_PHY_2),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_3, BASEMODE_VDSL_PHY_3),
+};
+
+static int bcm63268_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm63268_groups);
+}
+
+static const char *bcm63268_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm63268_groups[group].name;
+}
+
+static int bcm63268_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm63268_groups[group].pins;
+ *num_pins = bcm63268_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm63268_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm63268_funcs);
+}
+
+static const char *bcm63268_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm63268_funcs[selector].name;
+}
+
+static int bcm63268_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm63268_funcs[selector].groups;
+ *num_groups = bcm63268_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm63268_rmw_mux(struct bcm63268_pinctrl *pctl, void __iomem *reg,
+ u32 mask, u32 val)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ tmp = __raw_readl(reg);
+ tmp &= ~mask;
+ tmp |= val;
+ __raw_writel(tmp, reg);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static void bcm63268_set_gpio(struct bcm63268_pinctrl *pctl, unsigned pin)
+{
+ const struct pinctrl_pin_desc *desc = &bcm63268_pins[pin];
+ u32 basemode = (unsigned long)desc->drv_data;
+ u32 mask = BIT(pin % 32);
+
+ if (basemode)
+ bcm63268_rmw_mux(pctl, pctl->basemode, basemode, 0);
+
+ if (pin < 32) {
+ /* base mode: 0 => gpio, 1 => mux function */
+ bcm63268_rmw_mux(pctl, pctl->mode, mask, 0);
+
+ /* pins 0-23 might be muxed to led */
+ if (pin < 24)
+ bcm63268_rmw_mux(pctl, pctl->led, mask, 0);
+ } else if (pin < 52) {
+ /* ctrl reg: 0 => wifi function, 1 => gpio */
+ bcm63268_rmw_mux(pctl, pctl->ctrl, mask, mask);
+ }
+}
+
+static int bcm63268_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm63268_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm63268_pingroup *grp = &bcm63268_groups[group];
+ const struct bcm63268_function *f = &bcm63268_funcs[selector];
+ unsigned i;
+ void __iomem *reg;
+ u32 val, mask;
+
+ for (i = 0; i < grp->num_pins; i++)
+ bcm63268_set_gpio(pctl, grp->pins[i]);
+
+ switch (f->reg) {
+ case BCM63268_LEDCTRL:
+ reg = pctl->led;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM63268_MODE:
+ reg = pctl->mode;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM63268_CTRL:
+ reg = pctl->ctrl;
+ mask = BIT(grp->pins[0]);
+ val = 0;
+ break;
+ case BCM63268_BASEMODE:
+ reg = pctl->basemode;
+ mask = f->mask;
+ val = f->mask;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ bcm63268_rmw_mux(pctl, reg, mask, val);
+
+ return 0;
+}
+
+static int bcm63268_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm63268_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ bcm63268_set_gpio(pctl, offset);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm63268_pctl_ops = {
+ .get_groups_count = bcm63268_pinctrl_get_group_count,
+ .get_group_name = bcm63268_pinctrl_get_group_name,
+ .get_group_pins = bcm63268_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm63268_pmx_ops = {
+ .get_functions_count = bcm63268_pinctrl_get_func_count,
+ .get_function_name = bcm63268_pinctrl_get_func_name,
+ .get_function_groups = bcm63268_pinctrl_get_groups,
+ .set_mux = bcm63268_pinctrl_set_mux,
+ .gpio_request_enable = bcm63268_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm63268_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm63268_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *led, *mode, *ctrl, *basemode;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "led");
+ led = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(led))
+ return PTR_ERR(led);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
+ ctrl = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "basemode");
+ basemode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(basemode))
+ return PTR_ERR(basemode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->led = led;
+ pctl->mode = mode;
+ pctl->ctrl = ctrl;
+ pctl->basemode = basemode;
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm63268_pctl_ops;
+ pctl->desc.pmxops = &bcm63268_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm63268_pins);
+ pctl->desc.pins = bcm63268_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM63268_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm63268_pinctrl_match[] = {
+ { .compatible = "brcm,bcm63268-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm63268_pinctrl_driver = {
+ .probe = bcm63268_pinctrl_probe,
+ .driver = {
+ .name = "bcm63268-pinctrl",
+ .of_match_table = bcm63268_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm63268_pinctrl_driver);

View file

@ -1,161 +0,0 @@
From e058fa1969019c2f6705c53c4130e364a877d4e6 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Sun, 26 Nov 2017 12:07:31 +0100
Subject: [PATCH] gpio: fix device tree gpio hogs on dual role gpio/pincontrol
controllers
For dual role gpio and pincontrol controller, the device registration
path is often:
pinctrl_register(...);
gpiochip_add_data(...);
gpiochip_add_pin_range(...);
If the device tree node has any gpio-hogs, the code will try to apply them
in the gpiochip_add_data step, but fail as they cannot be requested, as the
ranges are missing. But we also cannot first add the pinranges, as the
appropriate data structures are only initialized in gpiochip_add_data.
To fix this, defer gpio-hogs to the time pin ranges get added instead of
directly at chip request time, if the gpio-chip has a request method.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/gpio/gpiolib-of.c | 20 +++++++++++++++-----
drivers/gpio/gpiolib.c | 5 +++--
drivers/gpio/gpiolib.h | 8 ++++++++
3 files changed, 26 insertions(+), 7 deletions(-)
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -646,23 +646,30 @@ static struct gpio_desc *of_parse_own_gp
* of_gpiochip_add_hog - Add all hogs in a hog device node
* @chip: gpio chip to act on
* @hog: device node describing the hogs
+ * @start: first gpio to check
+ * @num: number of gpios to check
*
* Returns error if it fails otherwise 0 on success.
*/
-static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog)
+static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog,
+ unsigned int start, unsigned int num)
{
enum gpiod_flags dflags;
struct gpio_desc *desc;
unsigned long lflags;
const char *name;
unsigned int i;
- int ret;
+ int ret, hwgpio;
for (i = 0;; i++) {
desc = of_parse_own_gpio(hog, chip, i, &name, &lflags, &dflags);
if (IS_ERR(desc))
break;
+ hwgpio = gpio_chip_hwgpio(desc);
+ if (hwgpio < start || hwgpio >= (start + num))
+ continue;
+
ret = gpiod_hog(desc, name, lflags, dflags);
if (ret < 0)
return ret;
@@ -678,12 +685,15 @@ static int of_gpiochip_add_hog(struct gp
/**
* of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions
* @chip: gpio chip to act on
+ * @start: first gpio to check
+ * @num: number of gpios to check
*
- * This is only used by of_gpiochip_add to request/set GPIO initial
- * configuration.
+ * This is used by of_gpiochip_add, gpiochip_add_pingroup_range and
+ * gpiochip_add_pin_range to request/set GPIO initial configuration.
* It returns error if it fails otherwise 0 on success.
*/
-static int of_gpiochip_scan_gpios(struct gpio_chip *chip)
+int of_gpiochip_scan_gpios(struct gpio_chip *chip, unsigned int start,
+ unsigned int num)
{
struct device_node *np;
int ret;
@@ -692,7 +702,7 @@ static int of_gpiochip_scan_gpios(struct
if (!of_property_read_bool(np, "gpio-hog"))
continue;
- ret = of_gpiochip_add_hog(chip, np);
+ ret = of_gpiochip_add_hog(chip, np, start, num);
if (ret < 0) {
of_node_put(np);
return ret;
@@ -758,7 +768,7 @@ static int of_gpio_notify(struct notifie
if (chip == NULL)
return NOTIFY_OK; /* not for us */
- ret = of_gpiochip_add_hog(chip, rd->dn);
+ ret = of_gpiochip_add_hog(chip, rd->dn, 0, chip->ngpio);
if (ret < 0) {
pr_err("%s: failed to add hogs for %pOF\n", __func__,
rd->dn);
@@ -1037,9 +1047,11 @@ int of_gpiochip_add(struct gpio_chip *ch
of_node_get(chip->of_node);
- ret = of_gpiochip_scan_gpios(chip);
- if (ret)
- of_node_put(chip->of_node);
+ if (!chip->request) {
+ ret = of_gpiochip_scan_gpios(chip, 0, chip->ngpio);
+ if (ret)
+ of_node_put(chip->of_node);
+ }
return ret;
}
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1911,7 +1911,8 @@ int gpiochip_add_pingroup_range(struct g
list_add_tail(&pin_range->node, &gdev->pin_ranges);
- return 0;
+ return of_gpiochip_scan_gpios(gc, gpio_offset,
+ pin_range->range.npins);
}
EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
@@ -1968,7 +1969,7 @@ int gpiochip_add_pin_range(struct gpio_c
list_add_tail(&pin_range->node, &gdev->pin_ranges);
- return 0;
+ return of_gpiochip_scan_gpios(gc, gpio_offset, npins);
}
EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);
--- a/drivers/gpio/gpiolib-of.h
+++ b/drivers/gpio/gpiolib-of.h
@@ -13,6 +13,8 @@ struct gpio_desc *of_find_gpio(struct de
unsigned long *lookupflags);
int of_gpiochip_add(struct gpio_chip *gc);
void of_gpiochip_remove(struct gpio_chip *gc);
+int of_gpiochip_scan_gpios(struct gpio_chip *chip, unsigned int start,
+ unsigned int num);
int of_gpio_get_count(struct device *dev, const char *con_id);
bool of_gpio_need_valid_mask(const struct gpio_chip *gc);
#else
@@ -25,6 +27,12 @@ static inline struct gpio_desc *of_find_
}
static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
+static inline int of_gpiochip_scan_gpios(struct gpio_chip *chip,
+ unsigned int start,
+ unsigned int num)
+{
+ return 0;
+}
static inline int of_gpio_get_count(struct device *dev, const char *con_id)
{
return 0;

View file

@ -1,68 +0,0 @@
From: Adrian Schmutzler <freifunk@adrianschmutzler.de>
Date: Fri, 03 Apr 2020 19:50:03 +0200
Subject: add removed helper syscon_regmap_lookup_by_pdevname
The helper syscon_regmap_lookup_by_pdevname has been removed in 29d14b668d2f
("mfd: Remove unused helper syscon_regmap_lookup_by_pdevname") due to lack
of users.
Thus, we have to maintain it locally.
This patch includes a fix due to changes in driver_find_device;
kernel commit: 92ce7e83b4e5 ("driver_find_device: Unify the match function
with class_find_device()")
Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -205,6 +205,27 @@ struct regmap *syscon_regmap_lookup_by_c
}
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
+static int syscon_match_pdevname(struct device *dev, const void *data)
+{
+ return !strcmp(dev_name(dev), (const char *)data);
+}
+
+struct regmap *syscon_regmap_lookup_by_pdevname(const char *s)
+{
+ struct device *dev;
+ struct syscon *syscon;
+
+ dev = driver_find_device(&syscon_driver.driver, NULL, (void *)s,
+ syscon_match_pdevname);
+ if (!dev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ syscon = dev_get_drvdata(dev);
+
+ return syscon->regmap;
+}
+EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_pdevname);
+
struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
const char *property)
{
--- a/include/linux/mfd/syscon.h
+++ b/include/linux/mfd/syscon.h
@@ -20,6 +20,7 @@ struct device_node;
extern struct regmap *device_node_to_regmap(struct device_node *np);
extern struct regmap *syscon_node_to_regmap(struct device_node *np);
extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s);
+extern struct regmap *syscon_regmap_lookup_by_pdevname(const char *s);
extern struct regmap *syscon_regmap_lookup_by_phandle(
struct device_node *np,
const char *property);
@@ -43,6 +44,11 @@ static inline struct regmap *syscon_regm
{
return ERR_PTR(-ENOTSUPP);
}
+
+static inline struct regmap *syscon_regmap_lookup_by_pdevname(const char *s)
+{
+ return ERR_PTR(-ENOTSUPP);
+}
static inline struct regmap *syscon_regmap_lookup_by_phandle(
struct device_node *np,

View file

@ -1,11 +0,0 @@
--- a/drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
@@ -566,7 +566,7 @@ static int bcm6362_pinctrl_set_mux(struc
val = BIT(grp->pins[0]);
break;
case BCM6362_MODE:
- reg = pctl->ctrl;
+ reg = pctl->mode;
mask = BIT(grp->pins[0]);
val = BIT(grp->pins[0]);
break;

View file

@ -1,66 +0,0 @@
From 6ac09efa8f0e189ffe7dd7b0889289de56ee44cc Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 19 Jan 2014 12:18:03 +0100
Subject: [PATCH] USB: EHCI: allow limiting ports for ehci-platform
In the same way as the ohci platform driver allows limiting ports,
enable the same for ehci. This prevents a mismatch in the available
ports between ehci/ohci on USB 2.0 controllers.
This is needed if the USB host controller always reports the maximum
number of ports regardless of the number of available ports (because
one might be set to be usb device).
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
drivers/usb/host/ehci-hcd.c | 4 ++++
drivers/usb/host/ehci-platform.c | 2 ++
drivers/usb/host/ehci.h | 1 +
include/linux/usb/ehci_pdriver.h | 1 +
4 files changed, 8 insertions(+)
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -687,6 +687,10 @@ int ehci_setup(struct usb_hcd *hcd)
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ if (ehci->num_ports) {
+ ehci->hcs_params &= ~0xf; /* bits 3:0, ports on HC */
+ ehci->hcs_params |= ehci->num_ports;
+ }
ehci->sbrn = HCD_USB2;
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -65,6 +65,9 @@ static int ehci_platform_reset(struct us
ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
+ if (pdata->num_ports && pdata->num_ports <= 15)
+ ehci->num_ports = pdata->num_ports;
+
if (pdata->pre_setup) {
retval = pdata->pre_setup(hcd);
if (retval < 0)
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -203,6 +203,7 @@ struct ehci_hcd { /* one per controlle
u32 command;
/* SILICON QUIRKS */
+ unsigned int num_ports;
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */
--- a/include/linux/usb/ehci_pdriver.h
+++ b/include/linux/usb/ehci_pdriver.h
@@ -43,6 +43,7 @@ struct usb_hcd;
*/
struct usb_ehci_pdata {
int caps_offset;
+ unsigned int num_ports;
unsigned has_tt:1;
unsigned has_synopsys_hc_bug:1;
unsigned big_endian_desc:1;

View file

@ -1,484 +0,0 @@
From 5a50cb0d53344a2429831b00925d6183d4d332e1 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 9 Mar 2014 03:54:05 +0100
Subject: [PATCH 40/44] MIPS: BCM63XX: move device registration code into its
own file
Move device registration code into its own file to allow sharing it
between board implementations.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/Makefile | 1 +
arch/mips/bcm63xx/boards/board_bcm963xx.c | 188 +-------------------------
arch/mips/bcm63xx/boards/board_common.c | 215 ++++++++++++++++++++++++++++++
arch/mips/bcm63xx/boards/board_common.h | 8 ++
4 files changed, 223 insertions(+), 183 deletions(-)
create mode 100644 arch/mips/bcm63xx/boards/board_common.c
create mode 100644 arch/mips/bcm63xx/boards/board_common.h
--- a/arch/mips/bcm63xx/boards/Makefile
+++ b/arch/mips/bcm63xx/boards/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
+obj-y += board_common.o
obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -9,32 +9,20 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/platform_device.h>
-#include <linux/ssb/ssb.h>
#include <asm/addrspace.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
-#include <bcm63xx_dev_uart.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
#include <bcm63xx_nvram.h>
-#include <bcm63xx_dev_pci.h>
-#include <bcm63xx_dev_enet.h>
-#include <bcm63xx_dev_flash.h>
-#include <bcm63xx_dev_hsspi.h>
-#include <bcm63xx_dev_pcmcia.h>
-#include <bcm63xx_dev_spi.h>
-#include <bcm63xx_dev_usb_ehci.h>
-#include <bcm63xx_dev_usb_ohci.h>
-#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
+#include "board_common.h"
+
#include <uapi/linux/bcm933xx_hcs.h>
#define HCS_OFFSET_128K 0x20000
-static struct board_info board;
-
/*
* known 3368 boards
*/
@@ -679,52 +667,6 @@ static const struct board_info __initcon
};
/*
- * Register a sane SPROMv2 to make the on-board
- * bcm4318 WLAN work
- */
-#ifdef CONFIG_SSB_PCIHOST
-static struct ssb_sprom bcm63xx_sprom = {
- .revision = 0x02,
- .board_rev = 0x17,
- .country_code = 0x0,
- .ant_available_bg = 0x3,
- .pa0b0 = 0x15ae,
- .pa0b1 = 0xfa85,
- .pa0b2 = 0xfe8d,
- .pa1b0 = 0xffff,
- .pa1b1 = 0xffff,
- .pa1b2 = 0xffff,
- .gpio0 = 0xff,
- .gpio1 = 0xff,
- .gpio2 = 0xff,
- .gpio3 = 0xff,
- .maxpwr_bg = 0x004c,
- .itssi_bg = 0x00,
- .boardflags_lo = 0x2848,
- .boardflags_hi = 0x0000,
-};
-
-int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
-{
- if (bus->bustype == SSB_BUSTYPE_PCI) {
- memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
- return 0;
- } else {
- pr_err("unable to fill SPROM for given bustype\n");
- return -EINVAL;
- }
-}
-#endif /* CONFIG_SSB_PCIHOST */
-
-/*
- * return board name for /proc/cpuinfo
- */
-const char *board_get_name(void)
-{
- return board.name;
-}
-
-/*
* early init callback, read nvram data from flash and checksum it
*/
void __init board_prom_init(void)
@@ -783,137 +725,15 @@ void __init board_prom_init(void)
if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
continue;
/* copy, board desc array is marked initdata */
- memcpy(&board, bcm963xx_boards[i], sizeof(board));
+ board_early_setup(bcm963xx_boards[i]);
break;
}
- /* bail out if board is not found, will complain later */
- if (!board.name[0]) {
+ /* warn if board is not found, will complain later */
+ if (i == ARRAY_SIZE(bcm963xx_boards)) {
char name[17];
memcpy(name, board_name, 16);
name[16] = 0;
pr_err("unknown bcm963xx board: %s\n", name);
- return;
- }
-
- /* setup pin multiplexing depending on board enabled device,
- * this has to be done this early since PCI init is done
- * inside arch_initcall */
- val = 0;
-
-#ifdef CONFIG_PCI
- if (board.has_pci) {
- bcm63xx_pci_enabled = 1;
- if (BCMCPU_IS_6348())
- val |= GPIO_MODE_6348_G2_PCI;
- }
-#endif /* CONFIG_PCI */
-
- if (board.has_pccard) {
- if (BCMCPU_IS_6348())
- val |= GPIO_MODE_6348_G1_MII_PCCARD;
- }
-
- if (board.has_enet0 && !board.enet0.use_internal_phy) {
- if (BCMCPU_IS_6348())
- val |= GPIO_MODE_6348_G3_EXT_MII |
- GPIO_MODE_6348_G0_EXT_MII;
- }
-
- if (board.has_enet1 && !board.enet1.use_internal_phy) {
- if (BCMCPU_IS_6348())
- val |= GPIO_MODE_6348_G3_EXT_MII |
- GPIO_MODE_6348_G0_EXT_MII;
- }
-
- bcm_gpio_writel(val, GPIO_MODE_REG);
-}
-
-/*
- * second stage init callback, good time to panic if we couldn't
- * identify on which board we're running since early printk is working
- */
-void __init board_setup(void)
-{
- if (!board.name[0])
- panic("unable to detect bcm963xx board");
- pr_info("board name: %s\n", board.name);
-
- /* make sure we're running on expected cpu */
- if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
- panic("unexpected CPU for bcm963xx board");
-}
-
-static struct gpio_led_platform_data bcm63xx_led_data;
-
-static struct platform_device bcm63xx_gpio_leds = {
- .name = "leds-gpio",
- .id = 0,
- .dev.platform_data = &bcm63xx_led_data,
-};
-
-/*
- * third stage init callback, register all board devices.
- */
-int __init board_register_devices(void)
-{
- if (board.has_uart0)
- bcm63xx_uart_register(0);
-
- if (board.has_uart1)
- bcm63xx_uart_register(1);
-
- if (board.has_pccard)
- bcm63xx_pcmcia_register();
-
- if (board.has_enet0 &&
- !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
- bcm63xx_enet_register(0, &board.enet0);
-
- if (board.has_enet1 &&
- !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
- bcm63xx_enet_register(1, &board.enet1);
-
- if (board.has_enetsw &&
- !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
- bcm63xx_enetsw_register(&board.enetsw);
-
- if (board.has_usbd)
- bcm63xx_usbd_register(&board.usbd);
-
- if (board.has_ehci0)
- bcm63xx_ehci_register();
-
- if (board.has_ohci0)
- bcm63xx_ohci_register();
-
- /* Generate MAC address for WLAN and register our SPROM,
- * do this after registering enet devices
- */
-#ifdef CONFIG_SSB_PCIHOST
- if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
- memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
- if (ssb_arch_register_fallback_sprom(
- &bcm63xx_get_fallback_sprom) < 0)
- pr_err("failed to register fallback SPROM\n");
}
-#endif /* CONFIG_SSB_PCIHOST */
-
- bcm63xx_spi_register();
-
- bcm63xx_hsspi_register();
-
- bcm63xx_flash_register();
-
- bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
- bcm63xx_led_data.leds = board.leds;
-
- platform_device_register(&bcm63xx_gpio_leds);
-
- if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
- gpio_request_one(board.ephy_reset_gpio,
- board.ephy_reset_gpio_flags, "ephy-reset");
-
- return 0;
}
--- /dev/null
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -0,0 +1,214 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/ssb/ssb.h>
+#include <asm/addrspace.h>
+#include <bcm63xx_board.h>
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_dev_uart.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_nvram.h>
+#include <bcm63xx_gpio.h>
+#include <bcm63xx_dev_pci.h>
+#include <bcm63xx_dev_enet.h>
+#include <bcm63xx_dev_flash.h>
+#include <bcm63xx_dev_hsspi.h>
+#include <bcm63xx_dev_pcmcia.h>
+#include <bcm63xx_dev_spi.h>
+#include <bcm63xx_dev_usb_ehci.h>
+#include <bcm63xx_dev_usb_ohci.h>
+#include <bcm63xx_dev_usb_usbd.h>
+#include <board_bcm963xx.h>
+
+#define PFX "board: "
+
+static struct board_info board;
+
+/*
+ * Register a sane SPROMv2 to make the on-board
+ * bcm4318 WLAN work
+ */
+#ifdef CONFIG_SSB_PCIHOST
+static struct ssb_sprom bcm63xx_sprom = {
+ .revision = 0x02,
+ .board_rev = 0x17,
+ .country_code = 0x0,
+ .ant_available_bg = 0x3,
+ .pa0b0 = 0x15ae,
+ .pa0b1 = 0xfa85,
+ .pa0b2 = 0xfe8d,
+ .pa1b0 = 0xffff,
+ .pa1b1 = 0xffff,
+ .pa1b2 = 0xffff,
+ .gpio0 = 0xff,
+ .gpio1 = 0xff,
+ .gpio2 = 0xff,
+ .gpio3 = 0xff,
+ .maxpwr_bg = 0x004c,
+ .itssi_bg = 0x00,
+ .boardflags_lo = 0x2848,
+ .boardflags_hi = 0x0000,
+};
+
+int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
+{
+ if (bus->bustype == SSB_BUSTYPE_PCI) {
+ memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
+ return 0;
+ } else {
+ printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
+ return -EINVAL;
+ }
+}
+#endif
+
+/*
+ * return board name for /proc/cpuinfo
+ */
+const char *board_get_name(void)
+{
+ return board.name;
+}
+
+/*
+ * setup board for device registration
+ */
+void __init board_early_setup(const struct board_info *target)
+{
+ u32 val;
+
+ memcpy(&board, target, sizeof(board));
+
+ /* setup pin multiplexing depending on board enabled device,
+ * this has to be done this early since PCI init is done
+ * inside arch_initcall */
+ val = 0;
+
+#ifdef CONFIG_PCI
+ if (board.has_pci) {
+ bcm63xx_pci_enabled = 1;
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G2_PCI;
+ }
+#endif
+
+ if (board.has_pccard) {
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G1_MII_PCCARD;
+ }
+
+ if (board.has_enet0 && !board.enet0.use_internal_phy) {
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G3_EXT_MII |
+ GPIO_MODE_6348_G0_EXT_MII;
+ }
+
+ if (board.has_enet1 && !board.enet1.use_internal_phy) {
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G3_EXT_MII |
+ GPIO_MODE_6348_G0_EXT_MII;
+ }
+
+ bcm_gpio_writel(val, GPIO_MODE_REG);
+}
+
+
+/*
+ * second stage init callback, good time to panic if we couldn't
+ * identify on which board we're running since early printk is working
+ */
+void __init board_setup(void)
+{
+ if (!board.name[0])
+ panic("unable to detect bcm963xx board");
+ printk(KERN_INFO PFX "board name: %s\n", board.name);
+
+ /* make sure we're running on expected cpu */
+ if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
+ panic("unexpected CPU for bcm963xx board");
+}
+
+static struct gpio_led_platform_data bcm63xx_led_data;
+
+static struct platform_device bcm63xx_gpio_leds = {
+ .name = "leds-gpio",
+ .id = 0,
+ .dev.platform_data = &bcm63xx_led_data,
+};
+
+/*
+ * third stage init callback, register all board devices.
+ */
+int __init board_register_devices(void)
+{
+ if (board.has_uart0)
+ bcm63xx_uart_register(0);
+
+ if (board.has_uart1)
+ bcm63xx_uart_register(1);
+
+ if (board.has_pccard)
+ bcm63xx_pcmcia_register();
+
+ if (board.has_enet0 &&
+ !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
+ bcm63xx_enet_register(0, &board.enet0);
+
+ if (board.has_enet1 &&
+ !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
+ bcm63xx_enet_register(1, &board.enet1);
+
+ if (board.has_enetsw &&
+ !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
+ bcm63xx_enetsw_register(&board.enetsw);
+
+ if (board.has_usbd)
+ bcm63xx_usbd_register(&board.usbd);
+
+ if (board.has_ehci0)
+ bcm63xx_ehci_register();
+
+ if (board.has_ohci0)
+ bcm63xx_ohci_register();
+
+ /* Generate MAC address for WLAN and register our SPROM,
+ * do this after registering enet devices
+ */
+#ifdef CONFIG_SSB_PCIHOST
+ if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
+ memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ if (ssb_arch_register_fallback_sprom(
+ &bcm63xx_get_fallback_sprom) < 0)
+ pr_err(PFX "failed to register fallback SPROM\n");
+ }
+#endif
+
+ bcm63xx_spi_register();
+
+ bcm63xx_hsspi_register();
+
+ bcm63xx_flash_register();
+
+ bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
+ bcm63xx_led_data.leds = board.leds;
+
+ platform_device_register(&bcm63xx_gpio_leds);
+
+ if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
+ gpio_request_one(board.ephy_reset_gpio,
+ board.ephy_reset_gpio_flags, "ephy-reset");
+
+ return 0;
+}
--- /dev/null
+++ b/arch/mips/bcm63xx/boards/board_common.h
@@ -0,0 +1,8 @@
+#ifndef __BOARD_COMMON_H
+#define __BOARD_COMMON_H
+
+#include <board_bcm963xx.h>
+
+void board_early_setup(const struct board_info *board);
+
+#endif /* __BOARD_COMMON_H */

View file

@ -1,100 +0,0 @@
From 4e9c34a37bd3442b286ba55441bfe22c1ac5b65f Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 9 Mar 2014 04:08:06 +0100
Subject: [PATCH 41/44] MIPS: BCM63XX: pass a mac addresss allocator to board
setup
Pass a mac address allocator to board setup code to allow board
implementations to work with third party bootloaders not using nvram
for configuration storage.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/boards/board_bcm963xx.c | 3 ++-
arch/mips/bcm63xx/boards/board_common.c | 16 ++++++++++------
arch/mips/bcm63xx/boards/board_common.h | 3 ++-
3 files changed, 14 insertions(+), 8 deletions(-)
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -725,7 +725,8 @@ void __init board_prom_init(void)
if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
continue;
/* copy, board desc array is marked initdata */
- board_early_setup(bcm963xx_boards[i]);
+ board_early_setup(bcm963xx_boards[i],
+ bcm63xx_nvram_get_mac_address);
break;
}
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -18,7 +18,6 @@
#include <bcm63xx_dev_uart.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
-#include <bcm63xx_nvram.h>
#include <bcm63xx_gpio.h>
#include <bcm63xx_dev_pci.h>
#include <bcm63xx_dev_enet.h>
@@ -81,15 +80,20 @@ const char *board_get_name(void)
return board.name;
}
+static int (*board_get_mac_address)(u8 mac[ETH_ALEN]);
+
/*
* setup board for device registration
*/
-void __init board_early_setup(const struct board_info *target)
+void __init board_early_setup(const struct board_info *target,
+ int (*get_mac_address)(u8 mac[ETH_ALEN]))
{
u32 val;
memcpy(&board, target, sizeof(board));
+ board_get_mac_address = get_mac_address;
+
/* setup pin multiplexing depending on board enabled device,
* this has to be done this early since PCI init is done
* inside arch_initcall */
@@ -162,15 +166,15 @@ int __init board_register_devices(void)
bcm63xx_pcmcia_register();
if (board.has_enet0 &&
- !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
+ !board_get_mac_address(board.enet0.mac_addr))
bcm63xx_enet_register(0, &board.enet0);
if (board.has_enet1 &&
- !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
+ !board_get_mac_address(board.enet1.mac_addr))
bcm63xx_enet_register(1, &board.enet1);
if (board.has_enetsw &&
- !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
+ !board_get_mac_address(board.enetsw.mac_addr))
bcm63xx_enetsw_register(&board.enetsw);
if (board.has_usbd)
@@ -186,7 +190,7 @@ int __init board_register_devices(void)
* do this after registering enet devices
*/
#ifdef CONFIG_SSB_PCIHOST
- if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
+ if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
if (ssb_arch_register_fallback_sprom(
--- a/arch/mips/bcm63xx/boards/board_common.h
+++ b/arch/mips/bcm63xx/boards/board_common.h
@@ -3,6 +3,7 @@
#include <board_bcm963xx.h>
-void board_early_setup(const struct board_info *board);
+void board_early_setup(const struct board_info *board,
+ int (*get_mac_address)(u8 mac[ETH_ALEN]));
#endif /* __BOARD_COMMON_H */

View file

@ -1,455 +0,0 @@
From 301744ecbeece89ab3a9d6beef7802fa22598f00 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 30 Nov 2014 14:53:12 +0100
Subject: [PATCH 1/5] irqchip: add support for bcm6345-style periphery irq
controller
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
.../brcm,bcm6345-periph-intc.txt | 50 +++
drivers/irqchip/Kconfig | 4 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-bcm6345-periph.c | 339 ++++++++++++++++++++
include/linux/irqchip/irq-bcm6345-periph.h | 16 +
5 files changed, 410 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-periph-intc.txt
create mode 100644 drivers/irqchip/irq-bcm6345-periph.c
create mode 100644 include/linux/irqchip/irq-bcm6345-periph.h
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-periph-intc.txt
@@ -0,0 +1,50 @@
+Broadcom BCM6345 Level 1 periphery interrupt controller
+
+This block is a interrupt controller that is typically connected directly
+to one of the HW INT lines on each CPU. Every BCM63XX xDSL chip since
+BCM6345 has contained this hardware.
+
+Key elements of the hardware design include:
+
+- 32, 64, or 128 incoming level IRQ lines
+
+- All onchip peripherals are wired directly to an L2 input
+
+- A separate instance of the register set for each CPU, allowing individual
+ peripheral IRQs to be routed to any CPU
+
+- No atomic mask/unmask operations
+
+- No polarity/level/edge settings
+
+- No FIFO or priority encoder logic; software is expected to read all
+ 1-4 status words to determine which IRQs are pending
+
+Required properties:
+
+- compatible: Should be "brcm,bcm6345-periph-intc".
+- reg: Specifies the base physical address and size of the registers.
+ Multiple register addresses may be specified, and must match the amount of
+ parent interrupts.
+- interrupt-controller: Identifies the node as an interrupt controller.
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
+ source, should be 1.
+- interrupt-parent: Specifies the phandle to the parent interrupt controller
+ this one is cascaded from.
+- interrupts: Specifies the interrupt line(s) in the interrupt-parent controller
+ node, valid values depend on the type of parent interrupt controller.
+ Multiple lines are used to route interrupts to different cpus, with the first
+ assumed to be for the boot CPU.
+
+Example:
+
+periph_intc: interrupt-controller@f0406800 {
+ compatible = "brcm,bcm6345-periph-intc";
+ reg = <0x10000020 0x10>, <0x10000030 0x10>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpu_intc>;
+ interrupts = <2>, <3>;
+};
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -145,6 +145,10 @@ config DAVINCI_CP_INTC
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
+config BCM6345_PERIPH_IRQ
+ bool
+ select IRQ_DOMAIN
+
config DW_APB_ICTL
bool
select GENERIC_IRQ_CHIP
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32
obj-$(CONFIG_ARCH_MMP) += irq-mmp.o
obj-$(CONFIG_IRQ_MXS) += irq-mxs.o
obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o
+obj-$(CONFIG_BCM6345_PERIPH_IRQ) += irq-bcm6345-periph.o
obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o
obj-$(CONFIG_CLPS711X_IRQCHIP) += irq-clps711x.o
obj-$(CONFIG_OMPIC) += irq-ompic.o
--- /dev/null
+++ b/drivers/irqchip/irq-bcm6345-periph.c
@@ -0,0 +1,339 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
+ */
+
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqchip/irq-bcm6345-periph.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_BCM63XX
+#include <asm/mach-bcm63xx/bcm63xx_irq.h>
+
+#define VIRQ_BASE IRQ_INTERNAL_BASE
+#else
+#define VIRQ_BASE 0
+#endif
+
+#define MAX_WORDS 4
+#define MAX_PARENT_IRQS 2
+#define IRQS_PER_WORD 32
+
+struct intc_block {
+ int parent_irq;
+ void __iomem *base;
+ void __iomem *en_reg[MAX_WORDS];
+ void __iomem *status_reg[MAX_WORDS];
+ u32 mask_cache[MAX_WORDS];
+};
+
+struct intc_data {
+ struct irq_chip chip;
+ struct intc_block block[MAX_PARENT_IRQS];
+
+ int num_words;
+
+ struct irq_domain *domain;
+ raw_spinlock_t lock;
+};
+
+static void bcm6345_periph_irq_handle(struct irq_desc *desc)
+{
+ struct intc_data *data = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct intc_block *block;
+ unsigned int irq = irq_desc_get_irq(desc);
+ unsigned int idx;
+
+ chained_irq_enter(chip, desc);
+
+ for (idx = 0; idx < MAX_PARENT_IRQS; idx++)
+ if (irq == data->block[idx].parent_irq)
+ block = &data->block[idx];
+
+ for (idx = 0; idx < data->num_words; idx++) {
+ int base = idx * IRQS_PER_WORD;
+ unsigned long pending;
+ int hw_irq;
+
+ raw_spin_lock(&data->lock);
+ pending = __raw_readl(block->en_reg[idx]) &
+ __raw_readl(block->status_reg[idx]);
+ raw_spin_unlock(&data->lock);
+
+ for_each_set_bit(hw_irq, &pending, IRQS_PER_WORD) {
+ int virq;
+
+ virq = irq_find_mapping(data->domain, base + hw_irq);
+ generic_handle_irq(virq);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void __bcm6345_periph_enable(struct intc_block *block, int reg, int bit,
+ bool enable)
+{
+ u32 val;
+
+ val = __raw_readl(block->en_reg[reg]);
+ if (enable)
+ val |= BIT(bit);
+ else
+ val &= ~BIT(bit);
+ __raw_writel(val, block->en_reg[reg]);
+}
+
+static void bcm6345_periph_irq_mask(struct irq_data *data)
+{
+ unsigned int i, reg, bit;
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+
+ reg = hwirq / IRQS_PER_WORD;
+ bit = hwirq % IRQS_PER_WORD;
+
+ raw_spin_lock(&priv->lock);
+ for (i = 0; i < MAX_PARENT_IRQS; i++) {
+ struct intc_block *block = &priv->block[i];
+
+ if (!block->parent_irq)
+ break;
+
+ __bcm6345_periph_enable(block, reg, bit, false);
+ }
+ raw_spin_unlock(&priv->lock);
+}
+
+static void bcm6345_periph_irq_unmask(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ unsigned int i, reg, bit;
+
+ reg = hwirq / IRQS_PER_WORD;
+ bit = hwirq % IRQS_PER_WORD;
+
+ raw_spin_lock(&priv->lock);
+ for (i = 0; i < MAX_PARENT_IRQS; i++) {
+ struct intc_block *block = &priv->block[i];
+
+ if (!block->parent_irq)
+ break;
+
+ if (block->mask_cache[reg] & BIT(bit))
+ __bcm6345_periph_enable(block, reg, bit, true);
+ else
+ __bcm6345_periph_enable(block, reg, bit, false);
+ }
+ raw_spin_unlock(&priv->lock);
+}
+
+#ifdef CONFIG_SMP
+static int bcm6345_periph_set_affinity(struct irq_data *data,
+ const struct cpumask *mask, bool force)
+{
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ struct intc_data *priv = data->domain->host_data;
+ unsigned int i, reg, bit;
+ unsigned long flags;
+ bool enabled;
+ int cpu;
+
+ reg = hwirq / IRQS_PER_WORD;
+ bit = hwirq % IRQS_PER_WORD;
+
+ /* we could route to more than one cpu, but performance
+ suffers, so fix it to one.
+ */
+ cpu = cpumask_any_and(mask, cpu_online_mask);
+ if (cpu >= nr_cpu_ids)
+ return -EINVAL;
+
+ if (cpu >= MAX_PARENT_IRQS)
+ return -EINVAL;
+
+ if (!priv->block[cpu].parent_irq)
+ return -EINVAL;
+
+ raw_spin_lock_irqsave(&priv->lock, flags);
+ enabled = !irqd_irq_masked(data);
+ for (i = 0; i < MAX_PARENT_IRQS; i++) {
+ struct intc_block *block = &priv->block[i];
+
+ if (!block->parent_irq)
+ break;
+
+ if (i == cpu) {
+ block->mask_cache[reg] |= BIT(bit);
+ __bcm6345_periph_enable(block, reg, bit, enabled);
+ } else {
+ block->mask_cache[reg] &= ~BIT(bit);
+ __bcm6345_periph_enable(block, reg, bit, false);
+ }
+ }
+ raw_spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+#endif
+
+static int bcm6345_periph_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct intc_data *priv = d->host_data;
+
+ irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops bcm6345_periph_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ .map = bcm6345_periph_map,
+};
+
+static int __init __bcm6345_periph_intc_init(struct device_node *node,
+ int num_blocks, int *irq,
+ void __iomem **base, int num_words)
+{
+ struct intc_data *data;
+ unsigned int i, w, status_offset;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ raw_spin_lock_init(&data->lock);
+
+ status_offset = num_words * sizeof(u32);
+
+ for (i = 0; i < num_blocks; i++) {
+ struct intc_block *block = &data->block[i];
+
+ block->parent_irq = irq[i];
+ block->base = base[i];
+
+ for (w = 0; w < num_words; w++) {
+ int word_offset = sizeof(u32) * ((num_words - w) - 1);
+
+ block->en_reg[w] = base[i] + word_offset;
+ block->status_reg[w] = base[i] + status_offset;
+ block->status_reg[w] += word_offset;
+
+ /* route all interrupts to line 0 by default */
+ if (i == 0)
+ block->mask_cache[w] = 0xffffffff;
+ }
+
+ irq_set_handler_data(block->parent_irq, data);
+ irq_set_chained_handler(block->parent_irq,
+ bcm6345_periph_irq_handle);
+ }
+
+ data->num_words = num_words;
+
+ data->chip.name = "bcm6345-periph-intc";
+ data->chip.irq_mask = bcm6345_periph_irq_mask;
+ data->chip.irq_unmask = bcm6345_periph_irq_unmask;
+
+#ifdef CONFIG_SMP
+ if (num_blocks > 1)
+ data->chip.irq_set_affinity = bcm6345_periph_set_affinity;
+#endif
+
+ data->domain = irq_domain_add_simple(node, IRQS_PER_WORD * num_words,
+ VIRQ_BASE,
+ &bcm6345_periph_domain_ops, data);
+ if (!data->domain) {
+ kfree(data);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void __init bcm6345_periph_intc_init(int num_blocks, int *irq,
+ void __iomem **base, int num_words)
+{
+ __bcm6345_periph_intc_init(NULL, num_blocks, irq, base, num_words);
+}
+
+#ifdef CONFIG_OF
+static int __init bcm6345_periph_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct resource res;
+ int num_irqs, ret = -EINVAL;
+ int irqs[MAX_PARENT_IRQS] = { 0 };
+ void __iomem *bases[MAX_PARENT_IRQS] = { NULL };
+ int words = 0;
+ int i;
+
+ num_irqs = of_irq_count(node);
+
+ if (num_irqs < 1 || num_irqs > MAX_PARENT_IRQS)
+ return -EINVAL;
+
+ for (i = 0; i < num_irqs; i++) {
+ resource_size_t size;
+
+ irqs[i] = irq_of_parse_and_map(node, i);
+ if (!irqs[i])
+ goto out_unmap;
+
+ if (of_address_to_resource(node, i, &res))
+ goto out_unmap;
+
+ size = resource_size(&res);
+ switch (size) {
+ case 8:
+ case 16:
+ case 32:
+ size = size / 8;
+ break;
+ default:
+ goto out_unmap;
+ }
+
+ if (words && words != size) {
+ ret = -EINVAL;
+ goto out_unmap;
+ }
+ words = size;
+
+ bases[i] = of_iomap(node, i);
+ if (!bases[i]) {
+ ret = -ENOMEM;
+ goto out_unmap;
+ }
+ }
+
+ ret = __bcm6345_periph_intc_init(node, num_irqs, irqs, bases, words);
+ if (!ret)
+ return 0;
+
+out_unmap:
+ for (i = 0; i < num_irqs; i++) {
+ iounmap(bases[i]);
+ irq_dispose_mapping(irqs[i]);
+ }
+
+ return ret;
+}
+
+IRQCHIP_DECLARE(bcm6345_periph_intc, "brcm,bcm6345-l1-intc",
+ bcm6345_periph_of_init);
+#endif
--- /dev/null
+++ b/include/linux/irqchip/irq-bcm6345-periph.h
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2008 Nicolas Schichan <nschichan@freebox.fr>
+ */
+
+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H
+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H
+
+void bcm6345_periph_intc_init(int num_blocks, int *irq, void __iomem **base,
+ int num_words);
+
+#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H */

View file

@ -1,394 +0,0 @@
From cf908990d4a8ccdb73ee4484aa8cadad379ca314 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 30 Nov 2014 14:54:27 +0100
Subject: [PATCH 2/5] irqchip: add support for bcm6345-style external
interrupt controller
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
.../interrupt-controller/brcm,bcm6345-ext-intc.txt | 29 ++
drivers/irqchip/Kconfig | 4 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-bcm6345-ext.c | 287 ++++++++++++++++++++
include/linux/irqchip/irq-bcm6345-ext.h | 14 +
5 files changed, 335 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt
create mode 100644 drivers/irqchip/irq-bcm6345-ext.c
create mode 100644 include/linux/irqchip/irq-bcm6345-ext.h
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt
@@ -0,0 +1,29 @@
+Broadcom BCM6345-style external interrupt controller
+
+Required properties:
+
+- compatible: Should be "brcm,bcm6345-ext-intc" or "brcm,bcm6318-ext-intc".
+- reg: Specifies the base physical addresses and size of the registers.
+- interrupt-controller: identifies the node as an interrupt controller.
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
+ source, Should be 2.
+- interrupt-parent: Specifies the phandle to the parent interrupt controller
+ this one is cascaded from.
+- interrupts: Specifies the interrupt line(s) in the interrupt-parent controller
+ node, valid values depend on the type of parent interrupt controller.
+
+Optional properties:
+
+- brcm,field-width: Size of each field (mask, clear, sense, ...) in bits in the
+ register. Defaults to 4.
+
+Example:
+
+ext_intc: interrupt-controller@10000018 {
+ compatible = "brcm,bcm6345-ext-intc";
+ interrupt-parent = <&periph_intc>;
+ #interrupt-cells = <2>;
+ reg = <0x10000018 0x4>;
+ interrupt-controller;
+ interrupts = <24>, <25>, <26>, <27>;
+};
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -145,6 +145,10 @@ config DAVINCI_CP_INTC
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
+config BCM6345_EXT_IRQ
+ bool
+ select IRQ_DOMAIN
+
config BCM6345_PERIPH_IRQ
bool
select IRQ_DOMAIN
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32
obj-$(CONFIG_ARCH_MMP) += irq-mmp.o
obj-$(CONFIG_IRQ_MXS) += irq-mxs.o
obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o
+obj-$(CONFIG_BCM6345_EXT_IRQ) += irq-bcm6345-ext.o
obj-$(CONFIG_BCM6345_PERIPH_IRQ) += irq-bcm6345-periph.o
obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o
obj-$(CONFIG_CLPS711X_IRQCHIP) += irq-clps711x.o
--- /dev/null
+++ b/drivers/irqchip/irq-bcm6345-ext.c
@@ -0,0 +1,301 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
+ */
+
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqchip/irq-bcm6345-ext.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_BCM63XX
+#include <asm/mach-bcm63xx/bcm63xx_irq.h>
+
+#define VIRQ_BASE IRQ_EXTERNAL_BASE
+#else
+#define VIRQ_BASE 0
+#endif
+
+#define MAX_IRQS 4
+
+#define EXTIRQ_CFG_SENSE 0
+#define EXTIRQ_CFG_STAT 1
+#define EXTIRQ_CFG_CLEAR 2
+#define EXTIRQ_CFG_MASK 3
+#define EXTIRQ_CFG_BOTHEDGE 4
+#define EXTIRQ_CFG_LEVELSENSE 5
+
+struct intc_data {
+ struct irq_chip chip;
+ struct irq_domain *domain;
+ raw_spinlock_t lock;
+
+ int parent_irq[MAX_IRQS];
+ void __iomem *reg;
+ int shift;
+ unsigned int toggle_clear_on_ack:1;
+};
+
+static void bcm6345_ext_intc_irq_handle(struct irq_desc *desc)
+{
+ struct intc_data *data = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned int irq = irq_desc_get_irq(desc);
+ unsigned int idx;
+
+ chained_irq_enter(chip, desc);
+
+ for (idx = 0; idx < MAX_IRQS; idx++) {
+ if (data->parent_irq[idx] != irq)
+ continue;
+
+ generic_handle_irq(irq_find_mapping(data->domain, idx));
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void bcm6345_ext_intc_irq_ack(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ u32 reg;
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+ __raw_writel(reg | (1 << (hwirq + EXTIRQ_CFG_CLEAR * priv->shift)),
+ priv->reg);
+ if (priv->toggle_clear_on_ack)
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+}
+
+static void bcm6345_ext_intc_irq_mask(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ u32 reg;
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_MASK * priv->shift));
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+}
+
+static void bcm6345_ext_intc_irq_unmask(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ u32 reg;
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+ reg |= 1 << (hwirq + EXTIRQ_CFG_MASK * priv->shift);
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+}
+
+static int bcm6345_ext_intc_set_type(struct irq_data *data,
+ unsigned int flow_type)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ bool levelsense = 0, sense = 0, bothedge = 0;
+ u32 reg;
+
+ flow_type &= IRQ_TYPE_SENSE_MASK;
+
+ if (flow_type == IRQ_TYPE_NONE)
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+
+ switch (flow_type) {
+ case IRQ_TYPE_EDGE_BOTH:
+ bothedge = 1;
+ break;
+
+ case IRQ_TYPE_EDGE_RISING:
+ sense = 1;
+ break;
+
+ case IRQ_TYPE_EDGE_FALLING:
+ break;
+
+ case IRQ_TYPE_LEVEL_HIGH:
+ levelsense = 1;
+ sense = 1;
+ break;
+
+ case IRQ_TYPE_LEVEL_LOW:
+ levelsense = 1;
+ break;
+
+ default:
+ pr_err("bogus flow type combination given!\n");
+ return -EINVAL;
+ }
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+
+ if (levelsense)
+ reg |= 1 << (hwirq + EXTIRQ_CFG_LEVELSENSE * priv->shift);
+ else
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_LEVELSENSE * priv->shift));
+ if (sense)
+ reg |= 1 << (hwirq + EXTIRQ_CFG_SENSE * priv->shift);
+ else
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_SENSE * priv->shift));
+ if (bothedge)
+ reg |= 1 << (hwirq + EXTIRQ_CFG_BOTHEDGE * priv->shift);
+ else
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_BOTHEDGE * priv->shift));
+
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+
+ irqd_set_trigger_type(data, flow_type);
+ if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+ irq_set_handler_locked(data, handle_level_irq);
+ else
+ irq_set_handler_locked(data, handle_edge_irq);
+
+ return 0;
+}
+
+static int bcm6345_ext_intc_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct intc_data *priv = d->host_data;
+
+ irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops bcm6345_ext_domain_ops = {
+ .xlate = irq_domain_xlate_twocell,
+ .map = bcm6345_ext_intc_map,
+};
+
+static int __init __bcm6345_ext_intc_init(struct device_node *node,
+ int num_irqs, int *irqs,
+ void __iomem *reg, int shift,
+ bool toggle_clear_on_ack)
+{
+ struct intc_data *data;
+ unsigned int i;
+ int start = VIRQ_BASE;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ raw_spin_lock_init(&data->lock);
+
+ for (i = 0; i < num_irqs; i++) {
+ data->parent_irq[i] = irqs[i];
+
+ irq_set_handler_data(irqs[i], data);
+ irq_set_chained_handler(irqs[i], bcm6345_ext_intc_irq_handle);
+ }
+
+ data->reg = reg;
+ data->shift = shift;
+ data->toggle_clear_on_ack = toggle_clear_on_ack;
+
+ data->chip.name = "bcm6345-ext-intc";
+ data->chip.irq_ack = bcm6345_ext_intc_irq_ack;
+ data->chip.irq_mask = bcm6345_ext_intc_irq_mask;
+ data->chip.irq_unmask = bcm6345_ext_intc_irq_unmask;
+ data->chip.irq_set_type = bcm6345_ext_intc_set_type;
+
+ /*
+ * If we have less than 4 irqs, this is the second controller on
+ * bcm63xx. So increase the VIRQ start to not overlap with the first
+ * one, but only do so if we actually use a non-zero start.
+ *
+ * This can be removed when bcm63xx has no legacy users anymore.
+ */
+ if (start && num_irqs < 4)
+ start += 4;
+
+ data->domain = irq_domain_add_simple(node, num_irqs, start,
+ &bcm6345_ext_domain_ops, data);
+ if (!data->domain) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void __init bcm6345_ext_intc_init(int num_irqs, int *irqs, void __iomem *reg,
+ int shift)
+{
+ __bcm6345_ext_intc_init(NULL, num_irqs, irqs, reg, shift, false);
+}
+
+#ifdef CONFIG_OF
+static int __init bcm6345_ext_intc_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ int num_irqs, ret = -EINVAL;
+ unsigned i;
+ void __iomem *base;
+ int irqs[MAX_IRQS] = { 0 };
+ u32 shift;
+ bool toggle_clear_on_ack = false;
+
+ num_irqs = of_irq_count(node);
+
+ if (!num_irqs || num_irqs > MAX_IRQS)
+ return -EINVAL;
+
+ if (of_property_read_u32(node, "brcm,field-width", &shift))
+ shift = 4;
+
+ /* on BCM6318 setting CLEAR seems to continuously mask interrupts */
+ if (of_device_is_compatible(node, "brcm,bcm6318-ext-intc"))
+ toggle_clear_on_ack = true;
+
+ for (i = 0; i < num_irqs; i++) {
+ irqs[i] = irq_of_parse_and_map(node, i);
+ if (!irqs[i]) {
+ ret = -ENOMEM;
+ goto out_unmap;
+ }
+ }
+
+ base = of_iomap(node, 0);
+ if (!base)
+ goto out_unmap;
+
+ ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift,
+ toggle_clear_on_ack);
+ if (!ret)
+ return 0;
+out_unmap:
+ iounmap(base);
+
+ for (i = 0; i < num_irqs; i++)
+ irq_dispose_mapping(irqs[i]);
+
+ return ret;
+}
+
+IRQCHIP_DECLARE(bcm6318_ext_intc, "brcm,bcm6318-ext-intc",
+ bcm6345_ext_intc_of_init);
+IRQCHIP_DECLARE(bcm6345_ext_intc, "brcm,bcm6345-ext-intc",
+ bcm6345_ext_intc_of_init);
+#endif
--- /dev/null
+++ b/include/linux/irqchip/irq-bcm6345-ext.h
@@ -0,0 +1,14 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
+ */
+
+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H
+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H
+
+void bcm6345_ext_intc_init(int n_irqs, int *irqs, void __iomem *reg, int shift);
+
+#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H */

View file

@ -1,687 +0,0 @@
From d2d2489e0a4b740abd980e9d1cad952d15bc2d9e Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 30 Nov 2014 14:55:02 +0100
Subject: [PATCH] MIPS: BCM63XX: switch to IRQ_DOMAIN
Now that we have working IRQ_DOMAIN drivers for both interrupt controllers,
switch to using them.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/Kconfig | 3 +
arch/mips/bcm63xx/irq.c | 612 +++++++++---------------------------------------
2 files changed, 108 insertions(+), 507 deletions(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -319,6 +319,9 @@ config BCM63XX
select SYNC_R4K
select DMA_NONCOHERENT
select IRQ_MIPS_CPU
+ select BCM6345_EXT_IRQ
+ select BCM6345_PERIPH_IRQ
+ select IRQ_DOMAIN
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_HAS_EARLY_PRINTK
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -11,7 +11,9 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/spinlock.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/irq-bcm6345-ext.h>
+#include <linux/irqchip/irq-bcm6345-periph.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <bcm63xx_cpu.h>
@@ -19,535 +21,140 @@
#include <bcm63xx_io.h>
#include <bcm63xx_irq.h>
-
-static DEFINE_SPINLOCK(ipic_lock);
-static DEFINE_SPINLOCK(epic_lock);
-
-static u32 irq_stat_addr[2];
-static u32 irq_mask_addr[2];
-static void (*dispatch_internal)(int cpu);
-static int is_ext_irq_cascaded;
-static unsigned int ext_irq_count;
-static unsigned int ext_irq_start, ext_irq_end;
-static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
-static void (*internal_irq_mask)(struct irq_data *d);
-static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m);
-
-
-static inline u32 get_ext_irq_perf_reg(int irq)
-{
- if (irq < 4)
- return ext_irq_cfg_reg1;
- return ext_irq_cfg_reg2;
-}
-
-static inline void handle_internal(int intbit)
-{
- if (is_ext_irq_cascaded &&
- intbit >= ext_irq_start && intbit <= ext_irq_end)
- do_IRQ(intbit - ext_irq_start + IRQ_EXTERNAL_BASE);
- else
- do_IRQ(intbit + IRQ_INTERNAL_BASE);
-}
-
-static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
- const struct cpumask *m)
-{
- bool enable = cpu_online(cpu);
-
-#ifdef CONFIG_SMP
- if (m)
- enable &= cpumask_test_cpu(cpu, m);
- else if (irqd_affinity_was_set(d))
- enable &= cpumask_test_cpu(cpu, irq_data_get_affinity_mask(d));
-#endif
- return enable;
-}
-
-/*
- * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
- * prioritize any interrupt relatively to another. the static counter
- * will resume the loop where it ended the last time we left this
- * function.
- */
-
-#define BUILD_IPIC_INTERNAL(width) \
-void __dispatch_internal_##width(int cpu) \
-{ \
- u32 pending[width / 32]; \
- unsigned int src, tgt; \
- bool irqs_pending = false; \
- static unsigned int i[2]; \
- unsigned int *next = &i[cpu]; \
- unsigned long flags; \
- \
- /* read registers in reverse order */ \
- spin_lock_irqsave(&ipic_lock, flags); \
- for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
- u32 val; \
- \
- val = bcm_readl(irq_stat_addr[cpu] + src * sizeof(u32)); \
- val &= bcm_readl(irq_mask_addr[cpu] + src * sizeof(u32)); \
- pending[--tgt] = val; \
- \
- if (val) \
- irqs_pending = true; \
- } \
- spin_unlock_irqrestore(&ipic_lock, flags); \
- \
- if (!irqs_pending) \
- return; \
- \
- while (1) { \
- unsigned int to_call = *next; \
- \
- *next = (*next + 1) & (width - 1); \
- if (pending[to_call / 32] & (1 << (to_call & 0x1f))) { \
- handle_internal(to_call); \
- break; \
- } \
- } \
-} \
- \
-static void __internal_irq_mask_##width(struct irq_data *d) \
-{ \
- u32 val; \
- unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
- unsigned reg = (irq / 32) ^ (width/32 - 1); \
- unsigned bit = irq & 0x1f; \
- unsigned long flags; \
- int cpu; \
- \
- spin_lock_irqsave(&ipic_lock, flags); \
- for_each_present_cpu(cpu) { \
- if (!irq_mask_addr[cpu]) \
- break; \
- \
- val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
- val &= ~(1 << bit); \
- bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
- } \
- spin_unlock_irqrestore(&ipic_lock, flags); \
-} \
- \
-static void __internal_irq_unmask_##width(struct irq_data *d, \
- const struct cpumask *m) \
-{ \
- u32 val; \
- unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
- unsigned reg = (irq / 32) ^ (width/32 - 1); \
- unsigned bit = irq & 0x1f; \
- unsigned long flags; \
- int cpu; \
- \
- spin_lock_irqsave(&ipic_lock, flags); \
- for_each_present_cpu(cpu) { \
- if (!irq_mask_addr[cpu]) \
- break; \
- \
- val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
- if (enable_irq_for_cpu(cpu, d, m)) \
- val |= (1 << bit); \
- else \
- val &= ~(1 << bit); \
- bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
- } \
- spin_unlock_irqrestore(&ipic_lock, flags); \
-}
-
-BUILD_IPIC_INTERNAL(32);
-BUILD_IPIC_INTERNAL(64);
-
-asmlinkage void plat_irq_dispatch(void)
-{
- u32 cause;
-
- do {
- cause = read_c0_cause() & read_c0_status() & ST0_IM;
-
- if (!cause)
- break;
-
- if (cause & CAUSEF_IP7)
- do_IRQ(7);
- if (cause & CAUSEF_IP0)
- do_IRQ(0);
- if (cause & CAUSEF_IP1)
- do_IRQ(1);
- if (cause & CAUSEF_IP2)
- dispatch_internal(0);
- if (is_ext_irq_cascaded) {
- if (cause & CAUSEF_IP3)
- dispatch_internal(1);
- } else {
- if (cause & CAUSEF_IP3)
- do_IRQ(IRQ_EXT_0);
- if (cause & CAUSEF_IP4)
- do_IRQ(IRQ_EXT_1);
- if (cause & CAUSEF_IP5)
- do_IRQ(IRQ_EXT_2);
- if (cause & CAUSEF_IP6)
- do_IRQ(IRQ_EXT_3);
- }
- } while (1);
-}
-
-/*
- * internal IRQs operations: only mask/unmask on PERF irq mask
- * register.
- */
-static void bcm63xx_internal_irq_mask(struct irq_data *d)
-{
- internal_irq_mask(d);
-}
-
-static void bcm63xx_internal_irq_unmask(struct irq_data *d)
-{
- internal_irq_unmask(d, NULL);
-}
-
-/*
- * external IRQs operations: mask/unmask and clear on PERF external
- * irq control register.
- */
-static void bcm63xx_external_irq_mask(struct irq_data *d)
-{
- unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
- u32 reg, regaddr;
- unsigned long flags;
-
- regaddr = get_ext_irq_perf_reg(irq);
- spin_lock_irqsave(&epic_lock, flags);
- reg = bcm_perf_readl(regaddr);
-
- if (BCMCPU_IS_6348())
- reg &= ~EXTIRQ_CFG_MASK_6348(irq % 4);
- else
- reg &= ~EXTIRQ_CFG_MASK(irq % 4);
-
- bcm_perf_writel(reg, regaddr);
- spin_unlock_irqrestore(&epic_lock, flags);
-
- if (is_ext_irq_cascaded)
- internal_irq_mask(irq_get_irq_data(irq + ext_irq_start));
-}
-
-static void bcm63xx_external_irq_unmask(struct irq_data *d)
-{
- unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
- u32 reg, regaddr;
- unsigned long flags;
-
- regaddr = get_ext_irq_perf_reg(irq);
- spin_lock_irqsave(&epic_lock, flags);
- reg = bcm_perf_readl(regaddr);
-
- if (BCMCPU_IS_6348())
- reg |= EXTIRQ_CFG_MASK_6348(irq % 4);
- else
- reg |= EXTIRQ_CFG_MASK(irq % 4);
-
- bcm_perf_writel(reg, regaddr);
- spin_unlock_irqrestore(&epic_lock, flags);
-
- if (is_ext_irq_cascaded)
- internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start),
- NULL);
-}
-
-static void bcm63xx_external_irq_clear(struct irq_data *d)
-{
- unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
- u32 reg, regaddr;
- unsigned long flags;
-
- regaddr = get_ext_irq_perf_reg(irq);
- spin_lock_irqsave(&epic_lock, flags);
- reg = bcm_perf_readl(regaddr);
-
- if (BCMCPU_IS_6348())
- reg |= EXTIRQ_CFG_CLEAR_6348(irq % 4);
- else
- reg |= EXTIRQ_CFG_CLEAR(irq % 4);
-
- bcm_perf_writel(reg, regaddr);
- spin_unlock_irqrestore(&epic_lock, flags);
-}
-
-static int bcm63xx_external_irq_set_type(struct irq_data *d,
- unsigned int flow_type)
-{
- unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
- u32 reg, regaddr;
- int levelsense, sense, bothedge;
- unsigned long flags;
-
- flow_type &= IRQ_TYPE_SENSE_MASK;
-
- if (flow_type == IRQ_TYPE_NONE)
- flow_type = IRQ_TYPE_LEVEL_LOW;
-
- levelsense = sense = bothedge = 0;
- switch (flow_type) {
- case IRQ_TYPE_EDGE_BOTH:
- bothedge = 1;
- break;
-
- case IRQ_TYPE_EDGE_RISING:
- sense = 1;
- break;
-
- case IRQ_TYPE_EDGE_FALLING:
- break;
-
- case IRQ_TYPE_LEVEL_HIGH:
- levelsense = 1;
- sense = 1;
- break;
-
- case IRQ_TYPE_LEVEL_LOW:
- levelsense = 1;
- break;
-
- default:
- pr_err("bogus flow type combination given !\n");
- return -EINVAL;
- }
-
- regaddr = get_ext_irq_perf_reg(irq);
- spin_lock_irqsave(&epic_lock, flags);
- reg = bcm_perf_readl(regaddr);
- irq %= 4;
-
- switch (bcm63xx_get_cpu_id()) {
- case BCM6348_CPU_ID:
- if (levelsense)
- reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq);
- else
- reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq);
- if (sense)
- reg |= EXTIRQ_CFG_SENSE_6348(irq);
- else
- reg &= ~EXTIRQ_CFG_SENSE_6348(irq);
- if (bothedge)
- reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq);
- else
- reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq);
- break;
-
- case BCM3368_CPU_ID:
- case BCM6328_CPU_ID:
- case BCM6338_CPU_ID:
- case BCM6345_CPU_ID:
- case BCM6358_CPU_ID:
- case BCM6362_CPU_ID:
- case BCM6368_CPU_ID:
- if (levelsense)
- reg |= EXTIRQ_CFG_LEVELSENSE(irq);
- else
- reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
- if (sense)
- reg |= EXTIRQ_CFG_SENSE(irq);
- else
- reg &= ~EXTIRQ_CFG_SENSE(irq);
- if (bothedge)
- reg |= EXTIRQ_CFG_BOTHEDGE(irq);
- else
- reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
- break;
- default:
- BUG();
- }
-
- bcm_perf_writel(reg, regaddr);
- spin_unlock_irqrestore(&epic_lock, flags);
-
- irqd_set_trigger_type(d, flow_type);
- if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
- irq_set_handler_locked(d, handle_level_irq);
- else
- irq_set_handler_locked(d, handle_edge_irq);
-
- return IRQ_SET_MASK_OK_NOCOPY;
-}
-
-#ifdef CONFIG_SMP
-static int bcm63xx_internal_set_affinity(struct irq_data *data,
- const struct cpumask *dest,
- bool force)
-{
- if (!irqd_irq_disabled(data))
- internal_irq_unmask(data, dest);
-
- return 0;
-}
-#endif
-
-static struct irq_chip bcm63xx_internal_irq_chip = {
- .name = "bcm63xx_ipic",
- .irq_mask = bcm63xx_internal_irq_mask,
- .irq_unmask = bcm63xx_internal_irq_unmask,
-};
-
-static struct irq_chip bcm63xx_external_irq_chip = {
- .name = "bcm63xx_epic",
- .irq_ack = bcm63xx_external_irq_clear,
-
- .irq_mask = bcm63xx_external_irq_mask,
- .irq_unmask = bcm63xx_external_irq_unmask,
-
- .irq_set_type = bcm63xx_external_irq_set_type,
-};
-
-static void bcm63xx_init_irq(void)
+void __init arch_init_irq(void)
{
- int irq_bits;
-
- irq_stat_addr[0] = bcm63xx_regset_address(RSET_PERF);
- irq_mask_addr[0] = bcm63xx_regset_address(RSET_PERF);
- irq_stat_addr[1] = bcm63xx_regset_address(RSET_PERF);
- irq_mask_addr[1] = bcm63xx_regset_address(RSET_PERF);
+ void __iomem *periph_bases[2];
+ void __iomem *ext_intc_bases[2];
+ int periph_irq_count, periph_width, ext_irq_count, ext_shift;
+ int periph_irqs[2] = { 2, 3 };
+ int ext_irqs[6];
+
+ periph_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
+ periph_bases[1] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
+ ext_intc_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
+ ext_intc_bases[1] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
switch (bcm63xx_get_cpu_id()) {
case BCM3368_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_3368_REG;
- irq_mask_addr[0] += PERF_IRQMASK_3368_REG;
- irq_stat_addr[1] = 0;
- irq_mask_addr[1] = 0;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
+ periph_bases[0] += PERF_IRQMASK_3368_REG;
+ periph_irq_count = 1;
+ periph_width = 1;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_3368;
+ ext_irq_count = 4;
+ ext_irqs[0] = BCM_3368_EXT_IRQ0;
+ ext_irqs[1] = BCM_3368_EXT_IRQ1;
+ ext_irqs[2] = BCM_3368_EXT_IRQ2;
+ ext_irqs[3] = BCM_3368_EXT_IRQ3;
+ ext_shift = 4;
break;
case BCM6328_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0);
- irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0);
- irq_stat_addr[1] += PERF_IRQSTAT_6328_REG(1);
- irq_mask_addr[1] += PERF_IRQMASK_6328_REG(1);
- irq_bits = 64;
- ext_irq_count = 4;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
+ periph_bases[0] += PERF_IRQMASK_6328_REG(0);
+ periph_bases[1] += PERF_IRQMASK_6328_REG(1);
+ periph_irq_count = 2;
+ periph_width = 2;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6328;
+ ext_irq_count = 4;
+ ext_irqs[0] = BCM_6328_EXT_IRQ0;
+ ext_irqs[1] = BCM_6328_EXT_IRQ1;
+ ext_irqs[2] = BCM_6328_EXT_IRQ2;
+ ext_irqs[3] = BCM_6328_EXT_IRQ3;
+ ext_shift = 4;
break;
case BCM6338_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6338_REG;
- irq_mask_addr[0] += PERF_IRQMASK_6338_REG;
- irq_stat_addr[1] = 0;
- irq_mask_addr[1] = 0;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
+ periph_bases[0] += PERF_IRQMASK_6338_REG;
+ periph_irq_count = 1;
+ periph_width = 1;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6338;
+ ext_irq_count = 4;
+ ext_irqs[0] = 3;
+ ext_irqs[1] = 4;
+ ext_irqs[2] = 5;
+ ext_irqs[3] = 6;
+ ext_shift = 4;
break;
case BCM6345_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6345_REG;
- irq_mask_addr[0] += PERF_IRQMASK_6345_REG;
- irq_stat_addr[1] = 0;
- irq_mask_addr[1] = 0;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
+ periph_bases[0] += PERF_IRQMASK_6345_REG;
+ periph_irq_count = 1;
+ periph_width = 1;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6345;
+ ext_irq_count = 4;
+ ext_irqs[0] = 3;
+ ext_irqs[1] = 4;
+ ext_irqs[2] = 5;
+ ext_irqs[3] = 6;
+ ext_shift = 4;
break;
case BCM6348_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6348_REG;
- irq_mask_addr[0] += PERF_IRQMASK_6348_REG;
- irq_stat_addr[1] = 0;
- irq_mask_addr[1] = 0;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
+ periph_bases[0] += PERF_IRQMASK_6348_REG;
+ periph_irq_count = 1;
+ periph_width = 1;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6348;
+ ext_irq_count = 4;
+ ext_irqs[0] = 3;
+ ext_irqs[1] = 4;
+ ext_irqs[2] = 5;
+ ext_irqs[3] = 6;
+ ext_shift = 5;
break;
case BCM6358_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6358_REG(0);
- irq_mask_addr[0] += PERF_IRQMASK_6358_REG(0);
- irq_stat_addr[1] += PERF_IRQSTAT_6358_REG(1);
- irq_mask_addr[1] += PERF_IRQMASK_6358_REG(1);
- irq_bits = 32;
- ext_irq_count = 4;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
+ periph_bases[0] += PERF_IRQMASK_6358_REG(0);
+ periph_bases[1] += PERF_IRQMASK_6358_REG(1);
+ periph_irq_count = 2;
+ periph_width = 1;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358;
+ ext_irq_count = 4;
+ ext_irqs[0] = BCM_6358_EXT_IRQ0;
+ ext_irqs[1] = BCM_6358_EXT_IRQ1;
+ ext_irqs[2] = BCM_6358_EXT_IRQ2;
+ ext_irqs[3] = BCM_6358_EXT_IRQ3;
+ ext_shift = 4;
break;
case BCM6362_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6362_REG(0);
- irq_mask_addr[0] += PERF_IRQMASK_6362_REG(0);
- irq_stat_addr[1] += PERF_IRQSTAT_6362_REG(1);
- irq_mask_addr[1] += PERF_IRQMASK_6362_REG(1);
- irq_bits = 64;
- ext_irq_count = 4;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
+ periph_bases[0] += PERF_IRQMASK_6362_REG(0);
+ periph_bases[1] += PERF_IRQMASK_6362_REG(1);
+ periph_irq_count = 2;
+ periph_width = 2;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6362;
+ ext_irq_count = 4;
+ ext_irqs[0] = BCM_6362_EXT_IRQ0;
+ ext_irqs[1] = BCM_6362_EXT_IRQ1;
+ ext_irqs[2] = BCM_6362_EXT_IRQ2;
+ ext_irqs[3] = BCM_6362_EXT_IRQ3;
+ ext_shift = 4;
break;
case BCM6368_CPU_ID:
- irq_stat_addr[0] += PERF_IRQSTAT_6368_REG(0);
- irq_mask_addr[0] += PERF_IRQMASK_6368_REG(0);
- irq_stat_addr[1] += PERF_IRQSTAT_6368_REG(1);
- irq_mask_addr[1] += PERF_IRQMASK_6368_REG(1);
- irq_bits = 64;
- ext_irq_count = 6;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
- ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
+ periph_bases[0] += PERF_IRQMASK_6368_REG(0);
+ periph_bases[1] += PERF_IRQMASK_6368_REG(1);
+ periph_irq_count = 2;
+ periph_width = 2;
+
+ ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6368;
+ ext_intc_bases[1] += PERF_EXTIRQ_CFG_REG2_6368;
+ ext_irq_count = 6;
+ ext_irqs[0] = BCM_6368_EXT_IRQ0;
+ ext_irqs[1] = BCM_6368_EXT_IRQ1;
+ ext_irqs[2] = BCM_6368_EXT_IRQ2;
+ ext_irqs[3] = BCM_6368_EXT_IRQ3;
+ ext_irqs[4] = BCM_6368_EXT_IRQ4;
+ ext_irqs[5] = BCM_6368_EXT_IRQ5;
+ ext_shift = 4;
break;
default:
BUG();
}
- if (irq_bits == 32) {
- dispatch_internal = __dispatch_internal_32;
- internal_irq_mask = __internal_irq_mask_32;
- internal_irq_unmask = __internal_irq_unmask_32;
- } else {
- dispatch_internal = __dispatch_internal_64;
- internal_irq_mask = __internal_irq_mask_64;
- internal_irq_unmask = __internal_irq_unmask_64;
- }
-}
-
-void __init arch_init_irq(void)
-{
- int i, irq;
-
- bcm63xx_init_irq();
mips_cpu_irq_init();
- for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i)
- irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip,
- handle_level_irq);
-
- for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + ext_irq_count; ++i)
- irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip,
- handle_edge_irq);
-
- if (!is_ext_irq_cascaded) {
- for (i = 3; i < 3 + ext_irq_count; ++i) {
- irq = MIPS_CPU_IRQ_BASE + i;
- if (request_irq(irq, no_action, IRQF_NO_THREAD,
- "cascade_extirq", NULL)) {
- pr_err("Failed to request irq %d (cascade_extirq)\n",
- irq);
- }
- }
- }
-
- irq = MIPS_CPU_IRQ_BASE + 2;
- if (request_irq(irq, no_action, IRQF_NO_THREAD, "cascade_ip2", NULL))
- pr_err("Failed to request irq %d (cascade_ip2)\n", irq);
-#ifdef CONFIG_SMP
- if (is_ext_irq_cascaded) {
- irq = MIPS_CPU_IRQ_BASE + 3;
- if (request_irq(irq, no_action, IRQF_NO_THREAD, "cascade_ip3",
- NULL))
- pr_err("Failed to request irq %d (cascade_ip3)\n", irq);
- bcm63xx_internal_irq_chip.irq_set_affinity =
- bcm63xx_internal_set_affinity;
-
- cpumask_clear(irq_default_affinity);
- cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
- }
-#endif
+ bcm6345_periph_intc_init(periph_irq_count, periph_irqs, periph_bases,
+ periph_width);
+ bcm6345_ext_intc_init(4, ext_irqs, ext_intc_bases[0], ext_shift);
+ if (ext_irq_count > 4)
+ bcm6345_ext_intc_init(2, &ext_irqs[4], ext_intc_bases[1],
+ ext_shift);
}

View file

@ -1,57 +0,0 @@
From 4fd286c3e5a5bebab0391cf1937695b3ed6721a3 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 30 Nov 2014 20:20:30 +0100
Subject: [PATCH 4/5] MIPS: BCM63XX: wire up BCM6358's external interrupts 4
and 5
Due to the external interrupts being non consecutive, the previous
implementation did not support them. Now that we treat both registers
as separate irq controllers, there is no such limitation anymore and
we can expose them for drivers to use.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/irq.c | 5 ++++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 2 ++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 1 +
3 files changed, 7 insertions(+), 1 deletion(-)
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -108,11 +108,14 @@ void __init arch_init_irq(void)
periph_width = 1;
ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358;
- ext_irq_count = 4;
+ ext_intc_bases[1] += PERF_EXTIRQ_CFG_REG2_6358;
+ ext_irq_count = 6;
ext_irqs[0] = BCM_6358_EXT_IRQ0;
ext_irqs[1] = BCM_6358_EXT_IRQ1;
ext_irqs[2] = BCM_6358_EXT_IRQ2;
ext_irqs[3] = BCM_6358_EXT_IRQ3;
+ ext_irqs[4] = BCM_6358_EXT_IRQ4;
+ ext_irqs[5] = BCM_6358_EXT_IRQ5;
ext_shift = 4;
break;
case BCM6362_CPU_ID:
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -896,6 +896,8 @@ enum bcm63xx_irq {
#define BCM_6358_EXT_IRQ1 (IRQ_INTERNAL_BASE + 26)
#define BCM_6358_EXT_IRQ2 (IRQ_INTERNAL_BASE + 27)
#define BCM_6358_EXT_IRQ3 (IRQ_INTERNAL_BASE + 28)
+#define BCM_6358_EXT_IRQ4 (IRQ_INTERNAL_BASE + 20)
+#define BCM_6358_EXT_IRQ5 (IRQ_INTERNAL_BASE + 21)
/*
* 6362 irqs
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -244,6 +244,7 @@
#define PERF_EXTIRQ_CFG_REG_6362 0x18
#define PERF_EXTIRQ_CFG_REG_6368 0x18
+#define PERF_EXTIRQ_CFG_REG2_6358 0x1c
#define PERF_EXTIRQ_CFG_REG2_6368 0x1c
/* for 6348 only */

View file

@ -1,20 +0,0 @@
--- a/drivers/irqchip/irq-bcm6345-periph.c
+++ b/drivers/irqchip/irq-bcm6345-periph.c
@@ -52,7 +52,7 @@ static void bcm6345_periph_irq_handle(st
{
struct intc_data *data = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
- struct intc_block *block;
+ struct intc_block *block = NULL;
unsigned int irq = irq_desc_get_irq(desc);
unsigned int idx;
@@ -62,7 +62,7 @@ static void bcm6345_periph_irq_handle(st
if (irq == data->block[idx].parent_irq)
block = &data->block[idx];
- for (idx = 0; idx < data->num_words; idx++) {
+ for (idx = 0; block && idx < data->num_words; idx++) {
int base = idx * IRQS_PER_WORD;
unsigned long pending;
int hw_irq;

View file

@ -1,28 +0,0 @@
--- a/drivers/irqchip/irq-bcm6345-ext.c
+++ b/drivers/irqchip/irq-bcm6345-ext.c
@@ -271,21 +271,19 @@ static int __init bcm6345_ext_intc_of_in
for (i = 0; i < num_irqs; i++) {
irqs[i] = irq_of_parse_and_map(node, i);
- if (!irqs[i]) {
- ret = -ENOMEM;
- goto out_unmap;
- }
+ if (!irqs[i])
+ return -ENOMEM;
}
base = of_iomap(node, 0);
if (!base)
- goto out_unmap;
+ return -ENXIO;
ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift,
toggle_clear_on_ack);
if (!ret)
return 0;
-out_unmap:
+
iounmap(base);
for (i = 0; i < num_irqs; i++)

View file

@ -1,20 +0,0 @@
--- a/drivers/irqchip/irq-bcm6345-periph.c
+++ b/drivers/irqchip/irq-bcm6345-periph.c
@@ -186,6 +186,8 @@ static int bcm6345_periph_set_affinity(s
}
raw_spin_unlock_irqrestore(&priv->lock, flags);
+ irq_data_update_effective_affinity(data, cpumask_of(cpu));
+
return 0;
}
#endif
@@ -197,6 +199,8 @@ static int bcm6345_periph_map(struct irq
irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
+
return 0;
}

View file

@ -1,12 +0,0 @@
--- a/drivers/irqchip/irq-bcm6345-periph.c
+++ b/drivers/irqchip/irq-bcm6345-periph.c
@@ -240,6 +240,9 @@ static int __init __bcm6345_periph_intc_
/* route all interrupts to line 0 by default */
if (i == 0)
block->mask_cache[w] = 0xffffffff;
+
+ /* mask all interrupts */
+ __raw_writel(0, block->en_reg[w]);
}
irq_set_handler_data(block->parent_irq, data);

View file

@ -1,77 +0,0 @@
From c50acd37b425a8a907a6f7f93aa2e658256e79ce Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:08:36 +0100
Subject: [PATCH 40/53] MIPS: BCM63XX: add a new cpu variant helper
---
arch/mips/bcm63xx/cpu.c | 10 ++++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 18 ++++++++++++++++++
2 files changed, 28 insertions(+)
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -27,6 +27,8 @@ EXPORT_SYMBOL(bcm63xx_irqs);
u16 bcm63xx_cpu_id __read_mostly;
EXPORT_SYMBOL(bcm63xx_cpu_id);
+static u32 bcm63xx_cpu_variant __read_mostly;
+
static u8 bcm63xx_cpu_rev;
static unsigned int bcm63xx_cpu_freq;
static unsigned int bcm63xx_memory_size;
@@ -99,6 +101,13 @@ static const int bcm6368_irqs[] = {
};
+u32 bcm63xx_get_cpu_variant(void)
+{
+ return bcm63xx_cpu_variant;
+}
+
+EXPORT_SYMBOL(bcm63xx_get_cpu_variant);
+
u8 bcm63xx_get_cpu_rev(void)
{
return bcm63xx_cpu_rev;
@@ -333,6 +342,7 @@ void __init bcm63xx_cpu_init(void)
/* read out CPU type */
tmp = bcm_readl(chipid_reg);
bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
+ bcm63xx_cpu_variant = bcm63xx_cpu_id;
bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
switch (bcm63xx_cpu_id) {
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -20,6 +20,7 @@
#define BCM6368_CPU_ID 0x6368
void __init bcm63xx_cpu_init(void);
+u32 bcm63xx_get_cpu_variant(void);
u8 bcm63xx_get_cpu_rev(void);
unsigned int bcm63xx_get_cpu_freq(void);
@@ -83,6 +84,23 @@ static inline u16 __pure bcm63xx_get_cpu
#define BCMCPU_IS_6362() (bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
#define BCMCPU_IS_6368() (bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
+#define BCMCPU_VARIANT_IS_3368() \
+ (bcm63xx_get_cpu_variant() == BCM3368_CPU_ID)
+#define BCMCPU_VARIANT_IS_6328() \
+ (bcm63xx_get_cpu_variant() == BCM6328_CPU_ID)
+#define BCMCPU_VARIANT_IS_6338() \
+ (bcm63xx_get_cpu_variant() == BCM6338_CPU_ID)
+#define BCMCPU_VARIANT_IS_6345() \
+ (bcm63xx_get_cpu_variant() == BCM6345_CPU_ID)
+#define BCMCPU_VARIANT_IS_6348() \
+ (bcm63xx_get_cpu_variant() == BCM6348_CPU_ID)
+#define BCMCPU_VARIANT_IS_6358() \
+ (bcm63xx_get_cpu_cariant() == BCM6358_CPU_ID)
+#define BCMCPU_VARIANT_IS_6362() \
+ (bcm63xx_get_cpu_variant() == BCM6362_CPU_ID)
+#define BCMCPU_VARIANT_IS_6368() \
+ (bcm63xx_get_cpu_variant() == BCM6368_CPU_ID)
+
/*
* While registers sets are (mostly) the same across 63xx CPU, base
* address of these sets do change.

View file

@ -1,23 +0,0 @@
From 3bd8e2535265f06f79ed9c0ad788405441e091dc Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:22:41 +0100
Subject: [PATCH 21/45] MIPS: BCM63XX: define variant id field
Some SoC have a variant id field in the chip id register.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 2 ++
1 file changed, 2 insertions(+)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -10,6 +10,8 @@
#define PERF_REV_REG 0x0
#define REV_CHIPID_SHIFT 16
#define REV_CHIPID_MASK (0xffff << REV_CHIPID_SHIFT)
+#define REV_VARID_SHIFT 12
+#define REV_VARID_MASK (0xf << REV_VARID_SHIFT)
#define REV_REVID_SHIFT 0
#define REV_REVID_MASK (0xff << REV_REVID_SHIFT)

View file

@ -1,68 +0,0 @@
From d59120f23279ef62a48d9f94847254b061d0a8b6 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:30:59 +0100
Subject: [PATCH 22/45] MIPS: BCM63XX: detect BCM6328 variants
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/cpu.c | 10 ++++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 8 ++++++--
2 files changed, 16 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -305,6 +305,7 @@ void __init bcm63xx_cpu_init(void)
unsigned int tmp;
unsigned int cpu = smp_processor_id();
u32 chipid_reg;
+ u8 __maybe_unused varid = 0;
/* soc registers location depends on cpu type */
chipid_reg = 0;
@@ -344,6 +345,7 @@ void __init bcm63xx_cpu_init(void)
bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
bcm63xx_cpu_variant = bcm63xx_cpu_id;
bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
+ varid = (tmp & REV_VARID_MASK) >> REV_VARID_SHIFT;
switch (bcm63xx_cpu_id) {
case BCM3368_CPU_ID:
@@ -353,6 +355,14 @@ void __init bcm63xx_cpu_init(void)
case BCM6328_CPU_ID:
bcm63xx_regs_base = bcm6328_regs_base;
bcm63xx_irqs = bcm6328_irqs;
+
+ if (varid == 1)
+ bcm63xx_cpu_variant = BCM63281_CPU_ID;
+ else if (varid == 3)
+ bcm63xx_cpu_variant = BCM63283_CPU_ID;
+ else
+ pr_warn("unknown BCM6328 variant: %x\n", varid);
+
break;
case BCM6338_CPU_ID:
bcm63xx_regs_base = bcm6338_regs_base;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -12,6 +12,8 @@
*/
#define BCM3368_CPU_ID 0x3368
#define BCM6328_CPU_ID 0x6328
+#define BCM63281_CPU_ID 0x63281
+#define BCM63283_CPU_ID 0x63283
#define BCM6338_CPU_ID 0x6338
#define BCM6345_CPU_ID 0x6345
#define BCM6348_CPU_ID 0x6348
@@ -86,8 +88,10 @@ static inline u16 __pure bcm63xx_get_cpu
#define BCMCPU_VARIANT_IS_3368() \
(bcm63xx_get_cpu_variant() == BCM3368_CPU_ID)
-#define BCMCPU_VARIANT_IS_6328() \
- (bcm63xx_get_cpu_variant() == BCM6328_CPU_ID)
+#define BCMCPU_VARIANT_IS_63281() \
+ (bcm63xx_get_cpu_variant() == BCM63281_CPU_ID)
+#define BCMCPU_VARIANT_IS_63283() \
+ (bcm63xx_get_cpu_variant() == BCM63283_CPU_ID)
#define BCMCPU_VARIANT_IS_6338() \
(bcm63xx_get_cpu_variant() == BCM6338_CPU_ID)
#define BCMCPU_VARIANT_IS_6345() \

View file

@ -1,46 +0,0 @@
From 04458c3db8eb79da21ecde40ab36a1dde52bef06 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:33:28 +0100
Subject: [PATCH 23/45] MIPS: BCM63XX: detect BCM6362 variants
---
arch/mips/bcm63xx/cpu.c | 8 ++++++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 3 +++
2 files changed, 11 insertions(+)
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -383,6 +383,14 @@ void __init bcm63xx_cpu_init(void)
case BCM6362_CPU_ID:
bcm63xx_regs_base = bcm6362_regs_base;
bcm63xx_irqs = bcm6362_irqs;
+
+ if (varid == 1)
+ bcm63xx_cpu_variant = BCM6362_CPU_ID;
+ else if (varid == 2)
+ bcm63xx_cpu_variant = BCM6361_CPU_ID;
+ else
+ pr_warn("unknown BCM6362 variant: %x\n", varid);
+
break;
case BCM6368_CPU_ID:
bcm63xx_regs_base = bcm6368_regs_base;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -18,6 +18,7 @@
#define BCM6345_CPU_ID 0x6345
#define BCM6348_CPU_ID 0x6348
#define BCM6358_CPU_ID 0x6358
+#define BCM6361_CPU_ID 0x6361
#define BCM6362_CPU_ID 0x6362
#define BCM6368_CPU_ID 0x6368
@@ -100,6 +101,8 @@ static inline u16 __pure bcm63xx_get_cpu
(bcm63xx_get_cpu_variant() == BCM6348_CPU_ID)
#define BCMCPU_VARIANT_IS_6358() \
(bcm63xx_get_cpu_cariant() == BCM6358_CPU_ID)
+#define BCMCPU_VARIANT_IS_6361() \
+ (bcm63xx_get_cpu_variant() == BCM6361_CPU_ID)
#define BCMCPU_VARIANT_IS_6362() \
(bcm63xx_get_cpu_variant() == BCM6362_CPU_ID)
#define BCMCPU_VARIANT_IS_6368() \

View file

@ -1,48 +0,0 @@
From 825cc67e56b5e624a05f6850a86d91508b786848 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sat, 7 Dec 2013 14:36:56 +0100
Subject: [PATCH 24/44] MIPS: BCM63XX: detect BCM6368 variants
The DSL-less BCM6368 variant BCM6367 uses a different chip id. Apart
from missing DSL, there is no difference to BCM6368, so treat it such.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
arch/mips/bcm63xx/cpu.c | 4 ++++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 3 +++
2 files changed, 7 insertions(+)
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -393,8 +393,12 @@ void __init bcm63xx_cpu_init(void)
break;
case BCM6368_CPU_ID:
+ case BCM6369_CPU_ID:
bcm63xx_regs_base = bcm6368_regs_base;
bcm63xx_irqs = bcm6368_irqs;
+
+ /* BCM6369 is a BCM6368 without xDSL, so treat it the same */
+ bcm63xx_cpu_id = BCM6368_CPU_ID;
break;
default:
panic("unsupported broadcom CPU %x", bcm63xx_cpu_id);
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -21,6 +21,7 @@
#define BCM6361_CPU_ID 0x6361
#define BCM6362_CPU_ID 0x6362
#define BCM6368_CPU_ID 0x6368
+#define BCM6369_CPU_ID 0x6369
void __init bcm63xx_cpu_init(void);
u32 bcm63xx_get_cpu_variant(void);
@@ -107,6 +108,8 @@ static inline u16 __pure bcm63xx_get_cpu
(bcm63xx_get_cpu_variant() == BCM6362_CPU_ID)
#define BCMCPU_VARIANT_IS_6368() \
(bcm63xx_get_cpu_variant() == BCM6368_CPU_ID)
+#define BCMCPU_VARIANT_IS_6369() \
+ (bcm63xx_get_cpu_variant() == BCM6369_CPU_ID)
/*
* While registers sets are (mostly) the same across 63xx CPU, base

View file

@ -1,20 +0,0 @@
From f67f8134b4537c8bbafe7e1975edfe808b813997 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 8 Dec 2013 03:05:54 +0100
Subject: [PATCH 45/53] MIPS: BCM63XX: fix PCIe memory window size
---
arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
@@ -42,7 +42,7 @@
BCM_CB_MEM_SIZE - 1)
#define BCM_PCIE_MEM_BASE_PA 0x10f00000
-#define BCM_PCIE_MEM_SIZE (16 * 1024 * 1024)
+#define BCM_PCIE_MEM_SIZE (1 * 1024 * 1024)
#define BCM_PCIE_MEM_END_PA (BCM_PCIE_MEM_BASE_PA + \
BCM_PCIE_MEM_SIZE - 1)

Some files were not shown because too many files have changed in this diff Show more