Merge branch 'stable-4.19-rk356x' of ssh://gitlab.ebf.local/rockchip/linux/kernel into stable-4.19-rk356x

This commit is contained in:
kalous12
2023-08-14 02:29:52 +00:00
20 changed files with 4539 additions and 833 deletions

View File

@ -38,6 +38,9 @@ dtbo-$(CONFIG_CPU_RK3568) += \
rk356x-lubancat-uart8-m1-overlay.dtbo \
rk356x-lubancat-uart9-m1-overlay.dtbo \
rk3566-lubancat-0-spi3-m1-gpio-cs-overlay.dtbo \
rk3566-lubancat-1h-edp-in-vp0-overlay.dtbo \
rk3566-lubancat-1h-lvds-10.1-in-vp0-overlay.dtbo \
rk3566-lubancat-1h-lvds-edp-touch-overlay.dtbo \
rk3566-lubancat-1io-dsi0-in-vp0-7.0-1024x600-overlay.dtbo \
rk3566-lubancat-1io-dsi0-in-vp0-10.1-800x1280-overlay.dtbo \
rk3566-lubancat-1io-dsi0-in-vp0-1080p-overlay.dtbo \

View File

@ -0,0 +1,139 @@
/dts-v1/;
/plugin/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rockchip.h>
#include <dt-bindings/display/drm_mipi_dsi.h>
#include <dt-bindings/interrupt-controller/irq.h>
/ {
fragment@0 {
target = <&route_edp>;
__overlay__ {
status = "okay";
connect = <&vp0_out_edp>;
};
};
fragment@1 {
target = <&edp_phy>;
__overlay__ {
status = "okay";
};
};
fragment@2 {
target = <&edp_in_vp0>;
__overlay__ {
status = "okay";
};
};
fragment@3 {
target = <&edp_in_vp1>;
__overlay__ {
status = "disabled";
};
};
fragment@4 {
target = <&edp>;
__overlay__ {
status = "okay";
// hpd-gpios = <&gpio4 RK_PC4 GPIO_ACTIVE_HIGH>; //热插拔信号检测
force-hpd; //强制hpd忽略物理hdp信号
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
edp_out_panel: endpoint@0 {
remote-endpoint = <&panel_in_edp>;
};
};
};
};
};
fragment@5 {
target-path = "/";
__overlay__ {
edp_panel: edp-panel {
compatible = "simple-panel";
backlight = <&backlight_lvds_edp>;
status = "okay";
enable-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_HIGH>;
//bus-format = <MEDIA_BUS_FMT_RBG888_1X24>;
prepare-delay-ms = <100>; //AUX通信前延时
enable-delay-ms = <100>;
display-timings {
native-mode = <&timing0>;
timing0: timing0 {
clock-frequency = <140000000>;
hactive = <1920>;
vactive = <1080>;
hfront-porch = <40>;
hsync-len = <40>;
hback-porch = <80>;
vfront-porch = <16>;
vsync-len = <8>;
vback-porch = <16>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
ports {
panel_in_edp: endpoint {
remote-endpoint = <&edp_out_panel>;
};
};
};
};
};
fragment@6 {
target = <&route_hdmi>;
__overlay__ {
status = "disabled";
};
};
fragment@7 {
target = <&hdmi_in_vp0>;
__overlay__ {
status = "disabled";
};
};
fragment@8 {
target = <&hdmi_in_vp1>;
__overlay__ {
status = "disabled";
};
};
fragment@9 {
target = <&hdmi>;
__overlay__ {
status = "disabled";
};
};
};

View File

@ -0,0 +1,194 @@
/dts-v1/;
/plugin/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rockchip.h>
#include <dt-bindings/display/drm_mipi_dsi.h>
#include <dt-bindings/interrupt-controller/irq.h>
/ {
fragment@0 {
target = <&route_dsi0>;
__overlay__ {
status = "okay";
connect = <&vp0_out_dsi0>;
};
};
fragment@1 {
target = <&video_phy0>;
__overlay__ {
status = "okay";
};
};
fragment@2 {
target = <&dsi0_in_vp0>;
__overlay__ {
status = "okay";
};
};
fragment@3 {
target = <&dsi0_in_vp1>;
__overlay__ {
status = "disabled";
};
};
fragment@4 {
target = <&dsi0>;
__overlay__ {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
dsi0_panel: panel@0 {
compatible = "simple-panel-dsi";
reg = <0>;
backlight = <&backlight_lvds_edp>;
reset-gpios = <&gpio4 RK_PC3 GPIO_ACTIVE_LOW>;
enable-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_HIGH>;
enable-delay-ms = <35>;
prepare-delay-ms = <6>;
reset-delay-ms = <0>;
init-delay-ms = <20>;
unprepare-delay-ms = <0>;
disable-delay-ms = <20>;
size,width = <74>;
size,height = <133>;
dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>;
dsi,format = <MIPI_DSI_FMT_RGB888>;
dsi,lanes = <4>;
panel-init-sequence = [
23 00 02 27 AA
23 00 02 48 02
23 00 02 B6 20
23 00 02 01 20
23 00 02 02 00
23 00 02 03 53
23 00 02 04 48
23 00 02 05 18
23 00 02 06 18
23 00 02 07 00
23 00 02 08 0C
23 00 02 09 02
23 00 02 0A 0A
23 00 02 0B 82
23 00 02 0C 22
23 00 02 0D 01
23 00 02 0E 80
23 00 02 0F 20
23 00 02 10 20
23 00 02 11 03
23 00 02 12 1B
23 00 02 13 03
23 00 02 14 01
23 00 02 15 23
23 00 02 16 40
23 00 02 17 00
23 00 02 18 01
23 00 02 19 23
23 00 02 1A 40
23 00 02 1B 00
23 00 02 1E 46
23 00 02 51 30
23 00 02 1F 10
23 00 02 2A 01
//如下为SSR展频不加可能点不亮
23 00 02 6A 08
23 00 02 6C 9E
23 00 02 6D 07
23 00 02 6E 00
23 00 02 6F 8A
23 00 02 70 19
23 64 02 71 00
];
disp_timings0: display-timings {
native-mode = <&dsi0_timing0>;
dsi0_timing0: timing0 {
clock-frequency = <60000000>;
hactive = <800>;
vactive = <1280>;
hsync-len = <24>;
hback-porch = <24>;
hfront-porch = <72>;
vsync-len = <2>;
vback-porch = <10>;
vfront-porch = <12>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
panel_in_dsi: endpoint {
remote-endpoint = <&dsi_out_panel>;
};
};
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
dsi_out_panel: endpoint {
remote-endpoint = <&panel_in_dsi>;
};
};
};
};
};
fragment@5 {
target = <&route_hdmi>;
__overlay__ {
status = "disabled";
};
};
fragment@6 {
target = <&hdmi_in_vp0>;
__overlay__ {
status = "disabled";
};
};
fragment@7 {
target = <&hdmi_in_vp1>;
__overlay__ {
status = "disabled";
};
};
fragment@8 {
target = <&hdmi>;
__overlay__ {
status = "disabled";
};
};
};

View File

@ -0,0 +1,32 @@
/dts-v1/;
/plugin/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rockchip.h>
#include <dt-bindings/display/drm_mipi_dsi.h>
#include <dt-bindings/interrupt-controller/irq.h>
/ {
fragment@0 {
target = <&i2c5>;
__overlay__ {
status = "okay";
clock-frequency = <100000>;
#address-cells = <1>;
#size-cells = <0>;
lvds_edp_gt911: lvds-edp-gt911@5d {
status = "okay";
compatible = "goodix,gt911";
reg = <0x5d>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PB7 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_LOW>;
irq-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
// touchscreen-inverted-x = <1>;
// touchscreen-inverted-y = <1>;
};
};
};
};

View File

@ -13,7 +13,7 @@
#include <dt-bindings/display/drm_mipi_dsi.h>
#include <dt-bindings/display/rockchip_vop.h>
#include <dt-bindings/sensor-dev.h>
#include "rk3568.dtsi"
#include "rk3566.dtsi"
//HDMI输出
#include "rk3566-lubancat-hdmi.dtsi"
@ -21,6 +21,8 @@
//MIPI摄像头配置
#include "rk3568-lubancat-csi2-double.dtsi"
//LVDS屏幕配置
// #include "rk3566-lubancat-lvds-10.1-800x1280.dtsi"
/ {
model = "EmbedFire LubanCat-1H";
@ -163,7 +165,7 @@
mini_pcie_3v3: mini-pcie-3v3-regulator {
compatible = "regulator-fixed";
regulator-name = "minipcie_3v3";
regulator-name = "mini_pcie_3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
enable-active-high;
@ -355,46 +357,46 @@
default-brightness-level = <200>;
};
backlight1: backlight1 {
status = "disable";
compatible = "pwm-backlight";
pwms = <&pwm5 0 50000 0>;
brightness-levels = <
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103
104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127
128 129 130 131 132 133 134 135
136 137 138 139 140 141 142 143
144 145 146 147 148 149 150 151
152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175
176 177 178 179 180 181 182 183
184 185 186 187 188 189 190 191
192 193 194 195 196 197 198 199
200 201 202 203 204 205 206 207
208 209 210 211 212 213 214 215
216 217 218 219 220 221 222 223
224 225 226 227 228 229 230 231
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255
>;
default-brightness-level = <200>;
};
backlight_lvds_edp: backlight-lvds-edp {
status = "okay";
compatible = "pwm-backlight";
pwms = <&pwm10 0 50000 0>;
brightness-levels = <
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103
104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127
128 129 130 131 132 133 134 135
136 137 138 139 140 141 142 143
144 145 146 147 148 149 150 151
152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175
176 177 178 179 180 181 182 183
184 185 186 187 188 189 190 191
192 193 194 195 196 197 198 199
200 201 202 203 204 205 206 207
208 209 210 211 212 213 214 215
216 217 218 219 220 221 222 223
224 225 226 227 228 229 230 231
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255
>;
default-brightness-level = <200>;
};
test-power {
status = "okay";
@ -468,8 +470,14 @@
&i2s1m0_sdo0>;
};
&pwm10 {
status = "okay";
};
&pwm11 {
status = "okay";
pinctrl-names = "active";
pinctrl-0 = <&pwm11m1_pins>;
};
&pwm13 {
@ -809,6 +817,19 @@
//mic-in-differential;
status = "okay";
};
rk809_rtc:rtc{
status = "disabled";
};
};
hym8563: hym8563@51 {
compatible = "haoyu,hym8563";
status = "okay";
reg = <0x51>;
#clock-cells = <0>;
clock-frequency = <32768>;
clock-output-names = "hym8563";
};
};
@ -1130,25 +1151,12 @@
status = "okay";
};
/* MULTI_PHY0 For SATA0, USB3.0 OTG Only USB2.0 */
&combphy0_us {
status = "okay";
};
/* USB3.0 OTG Only USB2.0 */
&usbdrd30 {
status = "okay";
};
&usbdrd_dwc3 {
phys = <&u2phy0_otg>;
phy-names = "usb2-phy";
extcon = <&usb2phy0>;
maximum-speed = "high-speed";
snps,dis_u2_susphy_quirk;
status = "okay";
};
&sata0 {
status = "okay";
};
@ -1216,6 +1224,10 @@
status = "okay";
};
&rockchip_suspend {
status = "okay";
};
&pinctrl {
cam {

View File

@ -4,53 +4,6 @@
*
*/
/ {
backlight_lvds_edp: backlight-lvds-edp {
status = "okay";
compatible = "pwm-backlight";
pwms = <&pwm10 0 50000 0>;
brightness-levels = <
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
95 95 95 95 95 95 95 95
88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103
104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127
128 129 130 131 132 133 134 135
136 137 138 139 140 141 142 143
144 145 146 147 148 149 150 151
152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175
176 177 178 179 180 181 182 183
184 185 186 187 188 189 190 191
192 193 194 195 196 197 198 199
200 201 202 203 204 205 206 207
208 209 210 211 212 213 214 215
216 217 218 219 220 221 222 223
224 225 226 227 228 229 230 231
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255
>;
default-brightness-level = <200>;
};
};
&pwm10 {
status = "okay";
};
&video_phy0 {
status = "okay";
};
@ -65,8 +18,7 @@
&dsi0 {
status = "okay";
power-supply = <&mipi_dsi0_power>;
// rockchip,lane-rate = <480>;
dsi0_panel: panel@0 {
compatible = "simple-panel-dsi";
reg = <0>;
@ -89,46 +41,54 @@
dsi,lanes = <4>;
panel-init-sequence = [
15 00 02 27 AA
15 00 02 48 02
15 00 02 B6 20
15 00 02 01 20
15 00 02 02 00
15 00 02 03 53
15 00 02 04 48
15 00 02 05 18
15 00 02 06 18
15 00 02 07 00
15 00 02 08 0C
15 00 02 09 02
15 00 02 0A 0A
15 00 02 0B 82
15 00 02 0C 13
15 00 02 0D 01
15 00 02 0E 80
15 00 02 0F 20
15 00 02 10 20
15 00 02 11 03
15 00 02 12 1B
15 00 02 13 53
15 00 02 14 01
15 00 02 15 23
15 00 02 16 40
15 00 02 17 00
15 00 02 18 01
15 00 02 19 23
15 00 02 1A 40
15 00 02 1B 00
15 00 02 1E 46
15 00 02 51 30
15 00 02 1F 10
15 00 02 2A 4D
23 00 02 27 AA
23 00 02 48 02
23 00 02 B6 20
23 00 02 01 20
23 00 02 02 00
23 00 02 03 53
23 00 02 04 48
23 00 02 05 18
23 00 02 06 18
23 00 02 07 00
23 00 02 08 0C
23 00 02 09 02
23 00 02 0A 0A
23 00 02 0B 82
23 00 02 0C 22
23 00 02 0D 01
23 00 02 0E 80
23 00 02 0F 20
23 00 02 10 20
23 00 02 11 03
23 00 02 12 1B
23 00 02 13 03
23 00 02 14 01
23 00 02 15 23
23 00 02 16 40
23 00 02 17 00
23 00 02 18 01
23 00 02 19 23
23 00 02 1A 40
23 00 02 1B 00
23 00 02 1E 46
23 00 02 51 30
23 00 02 1F 10
23 00 02 2A 01
//如下为SSR展频不加可能点不亮
23 00 02 6A 08
23 00 02 6C 9E
23 00 02 6D 07
23 00 02 6E 00
23 00 02 6F 8A
23 00 02 70 19
23 64 02 71 00
];
disp_timings0: display-timings {
native-mode = <&dsi0_timing0>;
dsi0_timing0: timing0 {
clock-frequency = <71980800>;
clock-frequency = <60000000>;
hactive = <800>;
vactive = <1280>;
hsync-len = <24>;
@ -169,6 +129,22 @@
};
};
&route_hdmi {
status = "disabled";
};
&hdmi_in_vp0 {
status = "disabled";
};
&hdmi_in_vp1 {
status = "disabled";
};
&hdmi {
status = "disabled";
};
&i2c5 {
status = "okay";
clock-frequency = <100000>;

View File

@ -12,9 +12,10 @@ enable_uboot_overlays=1
#dtoverlay=/dtb/overlay/rk3566-lubancat-1io-dsi1-in-vp0-10.1-800x1280-overlay.dtbo
#dtoverlay=/dtb/overlay/rk3566-lubancat-1io-dsi1-in-vp0-1080p-overlay.dtbo
#dtoverlay=/dtb/overlay/rk3566-lubancat-1io-dsi1-in-vp0-rpi-overlay.dtbo
#edp-in-vp0
#dtoverlay=/dtb/overlay/rk3566-lubancat-1io-edp-in-vp0-overlay.dtbo
#dtoverlay=/dtb/overlay/rk3566-lubancat-1io-edp-touch-overlay.dtbo
#edp-or-lvds-in-vp0
#dtoverlay=/dtb/overlay/rk3566-lubancat-1h-edp-in-vp0-overlay.dtbo
#dtoverlay=/dtb/overlay/rk3566-lubancat-1h-lvds-10.1-in-vp0-overlay.dtbo
#dtoverlay=/dtb/overlay/rk3566-lubancat-1h-lvds-edp-touch-overlay.dtbo
#cam0(mipi-csi0)
#dtoverlay=/dtb/overlay/rk356x-lubancat-csi0-sc132gs-overlay.dtbo
#dtoverlay=/dtb/overlay/rk356x-lubancat-csi0-ov5647-overlay.dtbo

View File

@ -208,15 +208,15 @@ CONFIG_CGROUP_NET_PRIO=y
CONFIG_CAN=y
CONFIG_CAN_ROCKCHIP=y
CONFIG_CANFD_ROCKCHIP=y
CONFIG_BT=y
CONFIG_BT=m
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_HIDP=y
CONFIG_BT_HCIBTUSB=y
CONFIG_BT_HCIBFUSB=y
CONFIG_BT_HCIVHCI=y
CONFIG_BT_MRVL=y
CONFIG_BT_MRVL_SDIO=y
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIBFUSB=m
CONFIG_BT_HCIVHCI=m
CONFIG_BT_MRVL=m
CONFIG_BT_MRVL_SDIO=m
CONFIG_NL80211_TESTMODE=y
CONFIG_CFG80211_DEBUGFS=y
CONFIG_CFG80211_WEXT=y
@ -304,7 +304,7 @@ CONFIG_STMMAC_ETH=y
# CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set
CONFIG_LED_TRIGGER_PHY=y
CONFIG_JLSEMI_JL2XX1_PHY=y
CONFIG_JLSEMI_PHY=y
CONFIG_ROCKCHIP_PHY=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
@ -752,6 +752,7 @@ CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y
CONFIG_UNICODE=y
CONFIG_CRYPTO_ECDH=y
# CONFIG_CRYPTO_ECHAINIV is not set
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_ANSI_CPRNG=y

View File

@ -787,7 +787,7 @@ static void rk817_shutdown_prepare(void)
/* close int when power off */
regmap_update_bits(rk808->regmap,
RK817_INT_STS_MSK_REG0,
0xff, 0xff);
0xff, 0xdf);
regmap_update_bits(rk808->regmap,
RK817_INT_STS_MSK_REG1,
0xff, 0xff);
@ -796,7 +796,7 @@ static void rk817_shutdown_prepare(void)
0xff, 0xff);
regmap_update_bits(rk808->regmap,
RK817_RTC_INT_REG,
(0x3 << 2), (0x0 << 2));
(0x1 << 2), (0x0 << 2));
dev_info(&rk808_i2c_client->dev, "disabled int when device shutdown!\n");

View File

@ -2200,8 +2200,6 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
atds = 1;
msleep(1500);
ret = stmmac_reset(priv, priv->ioaddr);
if (ret) {
dev_err(priv->device, "Failed to reset the dma\n");

View File

@ -365,11 +365,6 @@ int stmmac_mdio_register(struct net_device *ndev)
goto bus_register_fail;
}
stmmac_mdio_write(new_bus,0,31,2627);
stmmac_mdio_write(new_bus,0,25,0x1801);
stmmac_mdio_write(new_bus,0,31,0);
stmmac_mdio_write(new_bus,0,0,0x8000);
if (priv->plat->phy_node || mdio_node)
goto bus_register_done;

View File

@ -339,10 +339,10 @@ config INTEL_XWAY_PHY
PEF 7061, PEF 7071 and PEF 7072 or integrated into the Intel
SoCs xRX200, xRX300, xRX330, xRX350 and xRX550.
config JLSEMI_JL2XX1_PHY
tristate "JLSemi JL2XX1 PHYs"
config JLSEMI_PHY
tristate "JLSemi PHYs"
---help---
Currently supports the JLSemi jl2xx1 PHYs.
Currently supports the JLSemi PHYs.
config LSI_ET1011C_PHY
tristate "LSI ET1011C PHY"

View File

@ -65,8 +65,8 @@ obj-$(CONFIG_DP83867_PHY) += dp83867.o
obj-$(CONFIG_FIXED_PHY) += fixed_phy.o
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o
obj-$(CONFIG_JLSEMI_JL2XX1_PHY) += jl2xx1.o
jl2xx1-objs := jl2xxx.o jl2xxx-core.o
jlsemiphy-objs := jlsemi.o jlsemi-core.o
obj-$(CONFIG_JLSEMI_PHY) += jlsemiphy.o
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
obj-$(CONFIG_LXT_PHY) += lxt.o
obj-$(CONFIG_MARVELL_PHY) += marvell.o

View File

@ -1,438 +0,0 @@
/*
* Copyright (C) 2021 JLSemi Corporation
*
* 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.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "jl2xxx-core.h"
#include <linux/phy.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/netdevice.h>
#define RGMII_CTRL_PAGE 171
#define RGMII_CTRL_REG 17
#define RGMII_TX_SW_RSTN BIT(14)
#define RGMII_ERR_STAS BIT(3)
#define RGMII_TX_CTR_EN BIT(1)
#define RGMII_STATUS_PAGE 166
#define RGMII_STATUS_REG 18
#define BASIC_PAGE 0
#define BMCR_REG 0
#define SOFT_RESET BIT(15)
#define SPEED_LSB BIT(13)
#define AUTONEG_EN BIT(12)
#define SPEED_MSB BIT(6)
#define DIG_PAGE 201
#define DIG_REG 17
#define CLK_10M_EN BIT(15)
#define DAC_OUT_SEL_MSB BIT(1)
#define DAC_OUT_SEL_LSB BIT(0)
/************************* Configuration section *************************/
/************************* JLSemi iteration code *************************/
/* Patch for version: def2 */
uint32_t init_data[] = {
0x1f00a0, 0x1903f3, 0x1f0012, 0x150100, 0x1f00ad, 0x100000, 0x11e0c6, 0x1f00a0, 0x1903fb, 0x1903fb,
0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb, 0x1f00ad, 0x110000, 0x120400, 0x130093,
0x140000, 0x150193, 0x160000, 0x170213, 0x180000, 0x12040c, 0x130293, 0x140000, 0x150313, 0x160000,
0x170393, 0x180000, 0x120418, 0x130413, 0x140000, 0x150493, 0x160000, 0x170513, 0x180000, 0x120424,
0x130593, 0x140000, 0x150613, 0x160000, 0x170693, 0x180000, 0x120430, 0x130713, 0x140000, 0x150793,
0x160000, 0x171137, 0x180000, 0x12043c, 0x13006f, 0x140060, 0x15a001, 0x160113, 0x17fd41, 0x18d026,
0x120448, 0x13d406, 0x14d222, 0x1517b7, 0x160800, 0x17aa23, 0x189407, 0x120454, 0x130713, 0x1430f0,
0x1567b7, 0x160800, 0x17a423, 0x1846e7, 0x120460, 0x13a703, 0x14a587, 0x156685, 0x168f55, 0x17ac23,
0x18a4e7, 0x12046c, 0x1367b9, 0x145737, 0x150800, 0x168793, 0x17ef27, 0x182023, 0x120478, 0x1374f7,
0x1407b7, 0x150800, 0x165bfc, 0x17d493, 0x180037, 0x120484, 0x13f493, 0x141f04, 0x15f793, 0x1607f7,
0x178fc5, 0x18c03e, 0x120490, 0x134702, 0x140793, 0x150210, 0x160763, 0x1700f7, 0x180793, 0x12049c,
0x130270, 0x140c63, 0x1530f7, 0x16a001, 0x1707b7, 0x180002, 0x1204a8, 0x138793, 0x146967, 0x15c83e,
0x1617b7, 0x170002, 0x188793, 0x1204b4, 0x13e567, 0x14c43e, 0x1537b7, 0x160002, 0x178793, 0x186867,
0x1204c0, 0x13c23e, 0x1447b7, 0x150002, 0x168793, 0x17e9a7, 0x1866b7, 0x1204cc, 0x130800, 0x14ca3e,
0x15a783, 0x166d86, 0x1775c1, 0x188713, 0x1204d8, 0x130ff5, 0x148ff9, 0x156735, 0x160713, 0x178007,
0x188fd9, 0x1204e4, 0x13ac23, 0x146cf6, 0x15a783, 0x1665c6, 0x175737, 0x180800, 0x1204f0, 0x136611,
0x14f793, 0x15f0f7, 0x16e793, 0x170807, 0x18ae23, 0x1204fc, 0x1364f6, 0x142783, 0x155c47, 0x169bf5,
0x172223, 0x185cf7, 0x120508, 0x13a703, 0x14f5c6, 0x158f51, 0x16ae23, 0x17f4e6, 0x180737, 0x120514,
0x130809, 0x14433c, 0x158fd1, 0x16c33c, 0x170637, 0x180800, 0x120520, 0x134a74, 0x14679d, 0x158793,
0x160e07, 0x179ae1, 0x18e693, 0x12052c, 0x130036, 0x14ca74, 0x154678, 0x1676e1, 0x178693, 0x185006,
0x120538, 0x138ff9, 0x148fd5, 0x1507c2, 0x168f6d, 0x1783c1, 0x188fd9, 0x120544, 0x13c67c, 0x140713,
0x151000, 0x160793, 0x170000, 0x189c23, 0x120550, 0x1324e7, 0x140713, 0x151010, 0x169123, 0x1726e7,
0x18470d, 0x12055c, 0x13c63a, 0x144702, 0x158d23, 0x162407, 0x17a223, 0x182607, 0x120568, 0x130793,
0x140270, 0x150413, 0x160000, 0x171463, 0x1800f7, 0x120574, 0x134789, 0x14c63e, 0x154709, 0x16cc3a,
0x174702, 0x180793, 0x120580, 0x130270, 0x141463, 0x1500f7, 0x16478d, 0x17cc3e, 0x180513, 0x12058c,
0x130000, 0x144792, 0x154581, 0x164485, 0x179782, 0x184018, 0x120598, 0x131775, 0x14e563, 0x1502e4,
0x162703, 0x170a04, 0x181163, 0x1205a4, 0x130297, 0x144818, 0x150563, 0x160097, 0x1747a2, 0x18c804,
0x1205b0, 0x139782, 0x1466b7, 0x150800, 0x16a703, 0x174c46, 0x189b71, 0x1205bc, 0x136713, 0x140027,
0x15a223, 0x164ce6, 0x174783, 0x180fd4, 0x1205c8, 0x13c7b9, 0x142683, 0x151004, 0x164745, 0x179763,
0x1820e6, 0x1205d4, 0x133737, 0x140822, 0x152683, 0x163007, 0x177645, 0x18167d, 0x1205e0, 0x138ef1,
0x142023, 0x1530d7, 0x162683, 0x172807, 0x18e693, 0x1205ec, 0x131006, 0x142023, 0x1528d7, 0x162683,
0x173807, 0x18e693, 0x1205f8, 0x131006, 0x142023, 0x1538d7, 0x162683, 0x174007, 0x18e693, 0x120604,
0x131006, 0x142023, 0x1540d7, 0x162683, 0x174807, 0x18e693, 0x120610, 0x131006, 0x142023, 0x1548d7,
0x1656b7, 0x170800, 0x18a703, 0x12061c, 0x133486, 0x14830d, 0x158b05, 0x16cf01, 0x17a703, 0x185c46,
0x120628, 0x137671, 0x14167d, 0x158f71, 0x166611, 0x17a223, 0x185ce6, 0x120634, 0x138f51, 0x14a223,
0x155ce6, 0x162703, 0x171084, 0x1846b2, 0x120640, 0x131c63, 0x1402d7, 0x153737, 0x160822, 0x172683,
0x182807, 0x12064c, 0x13e693, 0x140016, 0x152023, 0x1628d7, 0x172683, 0x183807, 0x120658, 0x13e693,
0x140016, 0x152023, 0x1638d7, 0x172683, 0x184007, 0x120664, 0x13e693, 0x140016, 0x152023, 0x1640d7,
0x172683, 0x184807, 0x120670, 0x13e693, 0x140016, 0x152023, 0x1648d7, 0x172703, 0x181004, 0x12067c,
0x1346b2, 0x149c63, 0x151ae6, 0x160737, 0x170800, 0x184b78, 0x120688, 0x130693, 0x140ff0, 0x15463d,
0x168b1d, 0x17ce3a, 0x1852b7, 0x120694, 0x130800, 0x144701, 0x154389, 0x16408d, 0x174311, 0x180537,
0x1206a0, 0x130820, 0x141593, 0x150077, 0x1695aa, 0x17418c, 0x184572, 0x1206ac, 0x1305c2, 0x1481c1,
0x1581a9, 0x167763, 0x1700b5, 0x189533, 0x1206b8, 0x1300e4, 0x144513, 0x15fff5, 0x168e69, 0x170537,
0x180800, 0x1206c4, 0x134568, 0x148121, 0x15893d, 0x167463, 0x1702b5, 0x18a583, 0x1206d0, 0x1306c2,
0x140763, 0x151277, 0x160a63, 0x171217, 0x1805c2, 0x1206dc, 0x1381c1, 0x14818d, 0x150d63, 0x161097,
0x178985, 0x180586, 0x1206e8, 0x1395b3, 0x1400b4, 0x15c593, 0x16fff5, 0x178eed, 0x180705, 0x1206f4,
0x1315e3, 0x14fa67, 0x1535b7, 0x160822, 0x17a703, 0x183005, 0x120700, 0x13757d, 0x148a3d, 0x150513,
0x160ff5, 0x178f69, 0x180622, 0x12070c, 0x138e59, 0x14a023, 0x1530c5, 0x168637, 0x170800, 0x185a38,
0x120718, 0x1375c1, 0x14f693, 0x150ff6, 0x168593, 0x170ff5, 0x188f6d, 0x120724, 0x1306a2, 0x148ed9,
0x15da34, 0x164682, 0x170713, 0x180210, 0x120730, 0x139163, 0x140ee6, 0x154711, 0x16e391, 0x17471d,
0x182023, 0x12073c, 0x1310e4, 0x142683, 0x150a04, 0x16471d, 0x179e63, 0x1800e6, 0x120748, 0x136737,
0x140800, 0x152703, 0x164cc7, 0x170693, 0x184000, 0x120754, 0x137713, 0x144807, 0x151463, 0x1600d7,
0x172223, 0x180e04, 0x120760, 0x134018, 0x141163, 0x150497, 0x165703, 0x1700c4, 0x181793, 0x12076c,
0x130117, 0x14db63, 0x150207, 0x168737, 0x170800, 0x184778, 0x120778, 0x137713, 0x140807, 0x15e705,
0x160513, 0x170000, 0x184792, 0x120784, 0x134581, 0x149782, 0x1547a2, 0x164711, 0x17c818, 0x18c004,
0x120790, 0x130d23, 0x140094, 0x150ca3, 0x160004, 0x179782, 0x1856b7, 0x12079c, 0x130800, 0x1442b8,
0x159b71, 0x16c2b8, 0x170513, 0x180000, 0x1207a8, 0x1347d2, 0x149782, 0x154703, 0x162684, 0x1703e3,
0x18de07, 0x1207b4, 0x13bbd9, 0x1407b7, 0x150002, 0x168793, 0x1765c7, 0x18c83e, 0x1207c0, 0x1327b7,
0x140002, 0x158793, 0x16dae7, 0x17c43e, 0x1847b7, 0x1207cc, 0x130002, 0x148793, 0x151427, 0x16c23e,
0x1757b7, 0x180002, 0x1207d8, 0x138793, 0x149867, 0x15b1fd, 0x162683, 0x171504, 0x184709, 0x1207e4,
0x1399e3, 0x14e2e6, 0x1536b7, 0x160822, 0x17a703, 0x183006, 0x1207f0, 0x13663d, 0x148f51, 0x15a023,
0x1630e6, 0x17bd39, 0x18c593, 0x1207fc, 0x130015, 0x14b5dd, 0x158991, 0x1635b3, 0x1700b0, 0x180589,
0x120808, 0x13bdf9, 0x148991, 0x15b593, 0x160015, 0x17bfdd, 0x180737, 0x120814, 0x130800, 0x144f28,
0x15cf89, 0x1647c2, 0x17893d, 0x189782, 0x120820, 0x1347e2, 0x140713, 0x151000, 0x162223, 0x1710e4,
0x182423, 0x12082c, 0x1310f4, 0x14474d, 0x15b729, 0x168111, 0x17b7dd, 0x1814e3, 0x120838, 0x13f097,
0x140737, 0x150800, 0x164770, 0x171713, 0x180106, 0x120844, 0x135d63, 0x140607, 0x1585b7, 0x160800,
0x17a683, 0x180d05, 0x120850, 0x1372c5, 0x147313, 0x1500f6, 0x1612fd, 0x17a703, 0x180d45, 0x12085c,
0x131513, 0x1400c3, 0x15f6b3, 0x160056, 0x178ec9, 0x18757d, 0x120868, 0x130393, 0x140ff5, 0x151293,
0x160083, 0x17f6b3, 0x180076, 0x120874, 0x139b41, 0x148211, 0x15e2b3, 0x160056, 0x171093, 0x180043,
0x120880, 0x137693, 0x140016, 0x156333, 0x160067, 0x170613, 0x187ff5, 0x12088c, 0x139713, 0x1400b6,
0x157633, 0x1600c3, 0x178e59, 0x189513, 0x120898, 0x1300a6, 0x147613, 0x159ff6, 0x169713, 0x170096,
0x188e49, 0x1208a4, 0x13f293, 0x14f0f2, 0x158e59, 0x16e2b3, 0x170012, 0x1806a2, 0x1208b0, 0x137613,
0x14eff6, 0x158e55, 0x16a823, 0x170c55, 0x18aa23, 0x1208bc, 0x130cc5, 0x1480e3, 0x15e807, 0x1646b7,
0x170822, 0x18a703, 0x1208c8, 0x13f006, 0x149b61, 0x156713, 0x160027, 0x17a023, 0x18f0e6, 0x1208d4,
0x13b5ad, 0x140000, 0x150000, 0x160000, 0x170000, 0x180000, 0x110000, 0x120400, 0x104000, 0x1f0000,
};
int jl2xxx_pre_init(struct phy_device *phydev)
{
int i, j;
int regaddr, val;
int length = sizeof(init_data)/sizeof(init_data[0]);
for (i = 0; i < length; i++) {
regaddr = ((init_data[i] >> 16) & 0xff);
val = (init_data[i] & 0xffff);
phy_write(phydev, regaddr, val);
if (regaddr == 0x18) {
phy_write(phydev, 0x10, 0x8006);
for (j = 0; j < 8; j++) {
if (phy_read(phydev, 0x10) == 0) {
break;
}
}
}
}
return 0;
}
int enable_wol(struct phy_device *phydev)
{
jlsemi_set_bits(phydev, WOL_CTL_PAGE,
WOL_CTL_REG, WOL_EN);
jlsemi_clear_bits(phydev, WOL_CTL_STAS_PAGE,
WOL_CTL_STAS_REG, WOL_CTL_EN);
return 0;
}
int disable_wol(struct phy_device *phydev)
{
jlsemi_clear_bits(phydev, WOL_CTL_PAGE,
WOL_CTL_REG, WOL_EN);
jlsemi_set_bits(phydev, BASIC_PAGE, BMCR_REG, SOFT_RESET);
/* wait soft reset complete*/
msleep(20);
return 0;
}
int setup_wol_low_polarity(struct phy_device *phydev)
{
jlsemi_clear_bits(phydev, WOL_CTL_STAS_PAGE,
WOL_CTL_STAS_REG, WOL_POLARITY);
return 0;
}
int setup_wol_high_polarity(struct phy_device *phydev)
{
jlsemi_set_bits(phydev, WOL_CTL_STAS_PAGE,
WOL_CTL_STAS_REG, WOL_POLARITY);
return 0;
}
int clear_wol_event(struct phy_device *phydev)
{
jlsemi_set_bits(phydev, WOL_CTL_STAS_PAGE,
WOL_CTL_STAS_REG, WOL_EVENT);
jlsemi_clear_bits(phydev, WOL_CTL_STAS_PAGE,
WOL_CTL_STAS_REG, WOL_EVENT);
return 0;
}
int store_mac_addr(struct phy_device *phydev)
{
int err;
jlsemi_write_page(phydev, WOL_CTL_STAS_PAGE);
/* Store the device address for the magic packet */
err = phy_write(phydev, WOL_MAC_ADDR2_REG,
((phydev->attached_dev->dev_addr[0] << 8) |
phydev->attached_dev->dev_addr[1]));
if (err < 0)
return err;
err = phy_write(phydev, WOL_MAC_ADDR1_REG,
((phydev->attached_dev->dev_addr[2] << 8) |
phydev->attached_dev->dev_addr[3]));
if (err < 0)
return err;
err = phy_write(phydev, WOL_MAC_ADDR0_REG,
((phydev->attached_dev->dev_addr[4] << 8) |
phydev->attached_dev->dev_addr[5]));
if (err < 0)
return err;
/* change page to 0 */
jlsemi_write_page(phydev, BASIC_PAGE);
return 0;
}
int config_phy_info(struct phy_device *phydev,
struct jl2xx1_priv *jl2xx1)
{
int val, major, minor;
val = phy_read(phydev, 29);
if (val < 0)
return val;
major = (val >> 7) & 0x1f;
minor = (val >> 0) & 0x7f;
/* major enlarge 10 */
jl2xx1->sw_info = major * 10 + minor;
return 0;
}
/********************** Convenience function for phy **********************/
/**
* jlsemi_write_page() - write the page register
* @phydev: a pointer to a &struct phy_device
* @page: page values
*/
int jlsemi_write_page(struct phy_device *phydev, int page)
{
return phy_write(phydev, MII_JLSEMI_PHY_PAGE, page);
}
/**
* jlsemi_read_page() - write the page register
* @phydev: a pointer to a &struct phy_device
*
* Return: get page values at present
*/
int jlsemi_read_page(struct phy_device *phydev)
{
return phy_read(phydev, MII_JLSEMI_PHY_PAGE);
}
/**
* __jlsemi_save_page() - save the page value
*@phydev: a pointer to a &struct phy_device
*
* Return: save page value
*/
static inline int __jlsemi_save_page(struct phy_device *phydev)
{
return jlsemi_read_page(phydev);
}
/**
* __jlsemi_select_page() - restore the page register
* @phydev: a pointer to a &struct phy_device
* @page: the page
*
* Return:
* @oldpgae: this is last page value
* @ret: if page is change it will return new page value
*/
static inline int __jlsemi_select_page(struct phy_device *phydev, int page)
{
int ret, oldpage;
oldpage = ret = __jlsemi_save_page(phydev);
if (ret < 0)
return ret;
if (oldpage != page) {
ret = jlsemi_write_page(phydev, page);
if (ret < 0)
return ret;
}
return oldpage;
}
/**
* __jlsemi_restore_page() - restore the page register
* @phydev: a pointer to a &struct phy_device
* @oldpage: the old page, return value from __jlsemi_save_page() or
* __jlsemi_select_page()
* @ret: operation's return code
*
* Returns:
* @oldpage if it was a negative value, otherwise
* @ret if it was a negative errno value, otherwise
* phy_write_page()'s negative value if it were in error, otherwise
* @ret
*/
static inline int __jlsemi_restore_page(struct phy_device *phydev,
int oldpage, int ret)
{
int r;
if (oldpage >= 0) {
r = jlsemi_write_page(phydev, oldpage);
/* Propagate the operation return code if the page write
* was successful.
*/
if (ret >= 0 && r < 0)
ret = r;
} else {
/* Propagate the phy page selection error code */
ret = oldpage;
}
return ret;
}
/**
* __jlsemi_modify_reg() - Convenience function for modifying a PHY register
* @phydev: a pointer to a &struct phy_device
* @regnum: register number
* @mask: bit mask of bits to clear
* @set: bit mask of bits to set
*
* Returns negative errno, 0 if there was no change, and 1 in case of change
*/
static inline int __jlsemi_modify_reg(struct phy_device *phydev,
u32 regnum, u16 mask, u16 set)
{
int newval, ret;
ret = phy_read(phydev, regnum);
if (ret < 0)
return ret;
newval = (ret & ~mask) | set;
if (newval == ret)
return 0;
ret = phy_write(phydev, regnum, newval);
return ret < 0 ? ret : 1;
}
/**
* jlsemi_modify_paged_reg() - Function for modifying a paged register
* @phydev: a pointer to a &struct phy_device
* @page: the page for the phy
* @regnum: register number
* @mask: bit mask of bits to clear
* @set: bit mask of bits to set
*
* Returns negative errno, 0 if there was no change, and 1 in case of change
*/
int jlsemi_modify_paged_reg(struct phy_device *phydev,
int page, u32 regnum,
u16 mask, u16 set)
{
int ret = 0, oldpage;
oldpage = __jlsemi_select_page(phydev, page);
if (oldpage >= 0)
ret = __jlsemi_modify_reg(phydev, regnum, mask, set);
return __jlsemi_restore_page(phydev, oldpage, ret);
}
/**
* jlsemi_set_bits() - Convenience function for setting bits in a PHY register
* @phydev: a pointer to a &struct phy_device
* @page: the page for the phy
* @regnum: register number to write
* @val: bits to set
*/
int jlsemi_set_bits(struct phy_device *phydev,
int page, u32 regnum, u16 val)
{
return jlsemi_modify_paged_reg(phydev, page, regnum, 0, val);
}
/**
* jlsemi_clear_bits - Convenience function for clearing bits in a PHY register
* @phydev: the phy_device struct
* @page: the page for the phy
* @regnum: register number to write
* @val: bits to clear
*/
int jlsemi_clear_bits(struct phy_device *phydev,
int page, u32 regnum, u16 val)
{
return jlsemi_modify_paged_reg(phydev, page, regnum, val, 0);
}
/**
* jlsemi_get_bit() - Convenience function for setting bits in a PHY register
* @phydev: a pointer to a &struct phy_device
* @page: the page for the phy
* @regnum: register number to write
* @val: bit to get
*
* Note:
* you only get one bit at meanwhile
*
*/
int jlsemi_get_bit(struct phy_device *phydev,
int page, u32 regnum, u16 val)
{
int ret = 0, oldpage;
oldpage = __jlsemi_select_page(phydev, page);
if (oldpage >= 0)
{
ret = phy_read(phydev, regnum);
if (ret < 0)
return ret;
ret = ((ret & val) == val) ? 1 : 0;
}
return __jlsemi_restore_page(phydev, oldpage, ret);
}

View File

@ -1,104 +0,0 @@
/*
* Copyright (C) 2021 JLSemi Corporation
*
* 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.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _JLSEMI_CORE_H
#define _JLSEMI_CORE_H
#include <linux/phy.h>
#include <linux/version.h>
#include <linux/kernel.h>
#define JL2XX1_PHY_ID 0x937c4030
#define JLSEMI_PHY_ID_MASK 0xfffffff0
#define JL2101_PHY_ID 0x937c4032
#define MII_JLSEMI_PHY_PAGE 0x1f
#define WOL_CTL_PAGE 18
#define WOL_CTL_REG 21
#define WOL_CTL_STAS_PAGE 4608
#define WOL_CTL_STAS_REG 16
#define WOL_MAC_ADDR2_REG 17
#define WOL_MAC_ADDR1_REG 18
#define WOL_MAC_ADDR0_REG 19
#define WOL_EVENT BIT(1)
#define WOL_POLARITY BIT(14)
#define WOL_EN BIT(6)
#define WOL_CTL_EN BIT(15)
/************************* Configuration section *************************/
#define JLSEMI_WOL_EN 0
/************************* JLSemi iteration code *************************/
struct jl2xx1_priv {
u16 sw_info;
};
int jl2xxx_pre_init(struct phy_device *phydev);
int config_phy_info(struct phy_device *phydev,
struct jl2xx1_priv *jl2xx1);
int check_rgmii(struct phy_device *phydev);
int dis_rgmii_tx_ctrl(struct phy_device *phydev);
int config_suspend(struct phy_device *phydev);
int config_resume(struct phy_device *phydev);
int enable_wol(struct phy_device *phydev);
int disable_wol(struct phy_device *phydev);
int setup_wol_low_polarity(struct phy_device *phydev);
int setup_wol_high_polarity(struct phy_device *phydev);
int clear_wol_event(struct phy_device *phydev);
int store_mac_addr(struct phy_device *phydev);
int software_version(struct phy_device *phydev);
/********************** Convenience function for phy **********************/
/* Notice: You should change page 0 when you When you call it after*/
int jlsemi_write_page(struct phy_device *phydev, int page);
int jlsemi_read_page(struct phy_device *phydev);
int jlsemi_modify_paged_reg(struct phy_device *phydev,
int page, u32 regnum,
u16 mask, u16 set);
int jlsemi_set_bits(struct phy_device *phydev,
int page, u32 regnum, u16 val);
int jlsemi_clear_bits(struct phy_device *phydev,
int page, u32 regnum, u16 val);
int jlsemi_get_bit(struct phy_device *phydev,
int page, u32 regnum, u16 val);
int jlsemi_drivers_register(struct phy_driver *phydrvs, int size);
void jlsemi_drivers_unregister(struct phy_driver *phydrvs, int size);
#endif /* _JLSEMI_CORE_H */

View File

@ -1,127 +0,0 @@
/*
* drivers/net/phy/jlsemi.c
*
* Driver for JLSemi PHYs
*
* Author: Gangqiao Kuang <gqkuang@jlsemi.com>
*
* Copyright (c) 2021 JingLue Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include "jl2xxx-core.h"
#include <linux/phy.h>
#include <linux/module.h>
#include <linux/netdevice.h>
MODULE_DESCRIPTION("JLSemi PHY driver");
MODULE_AUTHOR("Gangqiao Kuang");
MODULE_LICENSE("GPL");
static int jlsemi_probe(struct phy_device *phydev)
{
int err;
err = jl2xxx_pre_init(phydev);
/* wait load complete*/
msleep(20);
return (err < 0) ? err : 0;
}
#if JLSEMI_WOL_EN
static void jlsemi_get_wol(struct phy_device *phydev,
struct ethtool_wolinfo *wol)
{
int wol_en;
wol->supported = WAKE_MAGIC;
wol->wolopts = 0;
wol_en = jlsemi_get_bit(phydev, WOL_CTL_PAGE,
WOL_CTL_REG, WOL_EN);
if (wol_en)
wol->wolopts |= WAKE_MAGIC;
}
static int jlsemi_set_wol(struct phy_device *phydev,
struct ethtool_wolinfo *wol)
{
int err;
if (wol->wolopts & WAKE_MAGIC) {
err = enable_wol(phydev);
if (err < 0)
return err;
err = clear_wol_event(phydev);
if (err < 0)
return err;
err = setup_wol_high_polarity(phydev);
if (err < 0)
return err;
err = store_mac_addr(phydev);
if (err < 0)
return err;
} else {
err = disable_wol(phydev);
if (err < 0)
return err;
err = setup_wol_high_polarity(phydev);
if (err < 0)
return err;
err = clear_wol_event(phydev);
if (err < 0)
return err;
}
return 0;
}
#endif
static struct phy_driver jlsemi_driver[] = {
{
PHY_ID_MATCH_EXACT(JL2101_PHY_ID),
.name = "JL2101 Gigabit Ethernet",
/* PHY_BASIC_FEATURES */
.features = PHY_GBIT_FEATURES,
.probe = jlsemi_probe,
#if JLSEMI_WOL_EN
.get_wol = jlsemi_get_wol,
.set_wol = jlsemi_set_wol,
#endif
},
{
PHY_ID_MATCH_MODEL(JL2XX1_PHY_ID),
.name = "JL2xx1 Gigabit Ethernet",
/* PHY_BASIC_FEATURES */
.features = PHY_GBIT_FEATURES,
.probe = jlsemi_probe,
#if JLSEMI_WOL_EN
.get_wol = jlsemi_get_wol,
.set_wol = jlsemi_set_wol,
#endif
},
};
module_phy_driver(jlsemi_driver);
static struct mdio_device_id __maybe_unused jlsemi_tbl[] = {
{ PHY_ID_MATCH_EXACT(JL2101_PHY_ID) },
{ PHY_ID_MATCH_MODEL(JL2XX1_PHY_ID) },
{ }
};
MODULE_DEVICE_TABLE(mdio, jlsemi_tbl);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,439 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* Copyright (C) 2021 JLSemi Corporation
*
* 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.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _JLSEMI_CORE_H
#define _JLSEMI_CORE_H
#define JLSEMI_KERNEL_DEVICE_TREE_USE 0
#include <linux/phy.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/of.h>
#if (JLSEMI_KERNEL_DEVICE_TREE_USE)
#include <dt-bindings/phy/jlsemi-dt-phy.h>
#else
#include "jlsemi-dt-phy.h"
#endif
#define JL1XXX_PHY_ID 0x937c4023
#define JL2XXX_PHY_ID 0x937c4032
#define JLSEMI_PHY_ID_MASK 0xfffffff0
#define JL1XXX_PAGE0 0
#define JL1XXX_PAGE7 7
#define JL1XXX_INTR_REG 19
#define JL1XXX_INTR_LINK BIT(13)
#define JL1XXX_INTR_AN_ERR BIT(11)
#define JL1XXX_LED_REG 19
#define JL1XXX_LED_EN BIT(3)
#define JL1XXX_INTR_STATUS_REG 30
#define JL1XXX_PAGE7 7
#define JL1XXX_RMII_CTRL_REG 16
#define JL1XXX_RMII_OUT BIT(12)
#define JL1XXX_RMII_MODE BIT(3)
#define JL1XXX_PAGE129 129
#define JL1XXX_LED_MODE_REG 24
#define JL1XXX_MAC_ADDR0_REG 25
#define JL1XXX_MAC_ADDR1_REG 26
#define JL1XXX_MAC_ADDR2_REG 27
#define JL1XXX_WOL_CTRL_REG 28
#define JL1XXX_WOL_DIS BIT(15)
#define JL1XXX_WOL_CLEAR BIT(1)
#define JL1xxx_WOL_RECEIVE BIT(0)
#define ADDR8_HIGH_TO_LOW(n) ((n >> 4) | (n << 4))
#define JL1XXX_PAGE24 24
#define JL1XXX_REG24 24
#define JL1XXX_MDI_TX_BM_MASK 0x1c00
#define JL1XXX_MDI_TX_BM(n) (n << 10)
#define JL1XXX_MDI_TX_SRN BIT(0)
#define JL1XXX_PAGE7 7
#define JL1XXX_REG16 16
#define JL1XXX_RMII_MODE BIT(3)
#define JL1XXX_RMII_CLK_50M_INPUT BIT(12)
#define JL1XXX_RMII_TX_SKEW_MASK (0xf << 8)
#define JL1XXX_RMII_TX_SKEW(n) ((n << 8) & JL1XXX_RMII_TX_SKEW_MASK)
#define JL1XXX_RMII_RX_SKEW_MASK (0xf << 4)
#define JL1XXX_RMII_RX_SKEW(n) ((n << 4) & JL1XXX_RMII_RX_SKEW_MASK)
#define JL1XXX_RMII_CRS_DV BIT(2)
#define JL2XXX_PAGE0 0
#define JL2XXX_BMCR_REG 0x0000
#define JL2XXX_SOFT_RESET BIT(15)
#define JL2XXX_SPEED_LSB BIT(13)
#define JL2XXX_AUTONEG_EN BIT(12)
#define JL2XXX_SPEED_MSB BIT(6)
#define JL2XXX_DSFT_CTRL_REG 17
#define JL2XXX_DSFT_EN BIT(12)
#define JL2XXX_DSFT_SMART_EN BIT(13)
#define JL2XXX_DSFT_TWO_WIRE_EN BIT(14)
#define JL2XXX_DSFT_AN_ERR_EN BIT(15)
#define JL2XXX_DSFT_STL_MASK 0x03e0
#define JL2XXX_DSFT_STL_CNT(n) (((n << 5) & JL2XXX_DSFT_STL_MASK))
#define JL2XXX_DSFT_AN_MASK 0x001f
#define JL2XXX_DSFT_CNT_MAX 32
#define JL2XXX_PHY_INFO_REG 29
#define JL2XXX_PATCH_MASK 0xffff
#define JL2XXX_SW_MASK 0xffff
#define JL2XXX_AUTO_GAIN_DIS BIT(6)
#define JLSEMI_PAGE31 0x001f
#define JL2XXX_WOL_CTRL_PAGE 0x0012
#define JL2XXX_WOL_CTRL_REG 0x0015
#define JL2XXX_WOL_STAS_PAGE 0x1200
#define JL2XXX_WOL_STAS_REG 0x0010
#define JL2XXX_MAC_ADDR2_REG 0x0011
#define JL2XXX_MAC_ADDR1_REG 0x0012
#define JL2XXX_MAC_ADDR0_REG 0x0013
#define JL2XXX_WOL_EVENT BIT(1)
#define JL2XXX_WOL_POLARITY BIT(14)
#define JL2XXX_WOL_EN BIT(15)
#define JL2XXX_WOL_GLB_EN BIT(6)
#define JL2XXX_PAGE2626 2626
#define JL2XXX_INTR_CTRL_REG 18
#define JL2XXX_INTR_LINK_CHANGE BIT(4)
#define JL2XXX_INTR_AN_COMPLETE BIT(3)
#define JL2XXX_INTR_AN_PAGE BIT(2)
#define JL2XXX_INTR_AN_ERR BIT(0)
#define JL2XXX_PAGE2627 2627
#define JL2XXX_INTR_STATUS_REG 29
#define JL2XXX_CLK_CTRL_REG 25
#define JL2XXX_CLK_OUT_PIN BIT(0)
#define JL2XXX_CLK_SSC_EN BIT(3)
#define JL2XXX_CLK_125M_OUT BIT(11)
#define JL2XXXX_CLK_SRC BIT(12)
#define JL2XXX_PAGE158 158
#define JL2XXX_INTR_PIN_REG 16
#define JL2XXX_INTR_PIN_EN BIT(14)
#define JL2XXX_PAGE160 160
#define JL2XXX_PIN_EN_REG 21
#define JL2XXX_PIN_OUTPUT BIT(11)
#define JL2XXX_PAGE3336 3336
#define JL2XXX_RGMII_CTRL_REG 17
#define JL2XXX_PAGE18 18
#define JL2XXX_RXC_OUT_REG 21
#define JL2XXX_RXC_OUT BIT(14)
#define JL2XXX_WORK_MODE_REG 21
#define JL2XXX_WORK_MODE_MASK 0x7
#define JL2XXX_PAGE160 160
#define JL2XXX_REG25 25
#define JL2XXX_CPU_RESET BIT(3)
#define JL2XXX_PAGE173 173
#define JL2XXX_PATCH_REG 0x0010
#define JL2XXX_REG16 16
#define JL2XXX_REG17 17
#define JL2XXX_LOAD_GO 0
#define JL2XXX_LOAD_DATA0 0x3a01
#define JL2XXX_REG20 20
#define JL2XXX_REG21 21
#define JL2XXX_LPBK_MODE_MASK 0x6
#define JL2XXX_LPBK_PMD_MODE BIT(2)
#define JL2XXX_LPBK_EXT_MODE BIT(1)
#define JL2XXX_PAGE174 174
#define JL2XXX_REG29 29
#define JL2XXX_PAGE191 191
#define JL2XXX_RGMII_CFG BIT(3)
#define JL2XXX_PAGE258 258
#define JL2XXX_SLEW_RATE_CTRL_REG 23
#define JL2XXX_SLEW_RATE_EN BIT(12)
#define JL2XXX_SLEW_RATE_REF_CLK BIT(13)
#define JL2XXX_SLEW_RATE_SEL_CLK BIT(14)
#define JL2XXX_REG20 20
#define JL2XXX_SPEED1000_NO_AN (BIT(11) | BIT(10))
#define LED_PERIOD_MASK 0xff00
#define LEDPERIOD(n) ((n << 8) & LED_PERIOD_MASK)
#define LED_ON_MASK 0x00ff
#define LEDON(n) ((n << 0) & LED_ON_MASK)
#define ADVERTISE_FIBER_1000HALF 0x40
#define ADVERTISE_FIBER_1000FULL 0x20
/*************************************************************************/
struct jl_hw_stat {
const char *string;
u8 reg;
u16 page;
u16 mask;
u16 enable;
};
static const struct jl_hw_stat jl_phy[] = {
{
.string = "page0,reg0",
.enable = true,
.page = 0,
.reg = 0,
}, {
.string = "page0,reg1",
.enable = false,
.page = 0,
.reg = 1,
},
};
static const struct jl_hw_stat jl2xxx_hw_stats[] = {
{
.string = "phy_patch_version",
.reg = JL2XXX_PATCH_REG,
.page = JL2XXX_PAGE174,
.mask = JL2XXX_PATCH_MASK,
}, {
.string = "phy_software_version",
.reg = JL2XXX_PHY_INFO_REG,
.page = JL2XXX_PAGE0,
.mask = JL2XXX_SW_MASK,
},
};
struct jl_led_ctrl {
u32 enable; /* LED control enable */
u32 mode; /* LED work mode */
u32 global_period; /* LED global twinkle period */
u32 global_on; /* LED global twinkle hold on time */
u32 gpio_output; /* LED is used as gpio output */
u32 polarity; /* LED polarity */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_fld_ctrl {
u32 enable; /* Fast link down control enable */
u32 delay; /* Fast link down time */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_wol_ctrl {
u32 enable; /* Wake On LAN control enable */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_intr_ctrl {
u32 enable; /* Interrupt control enable */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_downshift_ctrl {
u32 enable; /* Downshift control enable */
u32 count; /* Downshift control count */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_rgmii_ctrl {
u32 enable; /* Rgmii control enable */
u32 rx_delay; /* Rgmii control rx delay */
u32 tx_delay; /* Rgmii control tx delay */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_patch_ctrl {
u32 enable; /* Patch control enable */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_clk_ctrl {
u32 enable; /* Clock 125M control enable */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_work_mode_ctrl {
u32 enable; /* Work mode control enable */
u32 mode; /* Work mode select mode */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_loopback_ctrl {
u32 enable; /* Loopback control enable */
u32 mode; /* Loopback select mode */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_mdi_ctrl {
u32 enable; /* Mdi control enable */
u32 rate; /* Mdi select Rate */
u32 amplitude; /* Mdi select amplitude */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_rmii_ctrl {
u32 enable; /* Rmii control enable */
u32 tx_timing; /* Rmii modify tx timing */
u32 rx_timing; /* Rmii modify rx timing */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_slew_rate_ctrl {
u32 enable; /* Slew rate control enable */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl_rxc_out_ctrl {
u32 enable; /* Rx clock out control enable */
bool ethtool; /* Whether the ethtool is supported */
};
struct jl1xxx_priv {
struct jl_led_ctrl led;
struct jl_wol_ctrl wol;
struct jl_intr_ctrl intr;
bool static_inited; /* Initialization flag */
struct jl_mdi_ctrl mdi;
struct jl_rmii_ctrl rmii;
};
struct jl2xxx_priv {
struct jl_led_ctrl led;
struct jl_fld_ctrl fld;
struct jl_wol_ctrl wol;
struct jl_intr_ctrl intr;
struct jl_downshift_ctrl downshift;
struct jl_rgmii_ctrl rgmii;
struct jl_patch_ctrl patch;
struct jl_clk_ctrl clk;
const struct jl_hw_stat *hw_stats;
bool static_inited; /* Initialization flag */
int nstats; /* Record for dynamic operation */
u64 *stats; /* Pointer for dynamic operation */
struct jl_work_mode_ctrl work_mode;
struct jl_loopback_ctrl lpbk;
struct jl_slew_rate_ctrl slew_rate;
struct jl_rxc_out_ctrl rxc_out;
};
/* macros to simplify debug checking */
#define JLSEMI_PHY_MSG(msg, args...) printk(msg, ## args)
/************************* JLSemi iteration code *************************/
struct device *jlsemi_get_mdio(struct phy_device *phydev);
int jl2xxx_downshift_dynamic_op_get(struct phy_device *phydev, u8 *data);
int jl2xxx_downshift_dynamic_op_set(struct phy_device *phydev, u8 cnt);
int jlsemi_read_paged(struct phy_device *phydev, int page, u32 regnum);
int jl2xxx_intr_ack_event(struct phy_device *phydev);
int jl2xxx_intr_static_op_set(struct phy_device *phydev);
int jl1xxx_intr_ack_event(struct phy_device *phydev);
int jl1xxx_intr_static_op_set(struct phy_device *phydev);
int jl2xxx_wol_dynamic_op_get(struct phy_device *phydev);
int jl2xxx_wol_dynamic_op_set(struct phy_device *phydev);
int jl1xxx_wol_dynamic_op_get(struct phy_device *phydev);
int jl1xxx_wol_dynamic_op_set(struct phy_device *phydev);
int jl2xxx_fld_dynamic_op_get(struct phy_device *phydev, u8 *msecs);
int jl2xxx_fld_dynamic_op_set(struct phy_device *phydev, const u8 *msecs);
int jl1xxx_operation_args_get(struct phy_device *phydev);
int jl1xxx_static_op_init(struct phy_device *phydev);
int jl2xxx_operation_args_get(struct phy_device *phydev);
int jl2xxx_static_op_init(struct phy_device *phydev);
int jlsemi_soft_reset(struct phy_device *phydev);
int jl2xxx_pre_init(struct phy_device *phydev,
u32 *init_data, u16 data_len,
u16 *patch_fw_versions, u16 versions_len,
u16 patch_version);
bool jl2xxx_read_fiber_status(struct phy_device *phydev);
int jl2xxx_config_aneg_fiber(struct phy_device *phydev);
/********************** Convenience function for phy **********************/
/* Notice: You should change page 0 when you When you call it after */
int jlsemi_write_page(struct phy_device *phydev, int page);
int jlsemi_read_page(struct phy_device *phydev);
int jlsemi_modify_paged_reg(struct phy_device *phydev,
int page, u32 regnum,
u16 mask, u16 set);
int jlsemi_set_bits(struct phy_device *phydev,
int page, u32 regnum, u16 val);
int jlsemi_clear_bits(struct phy_device *phydev,
int page, u32 regnum, u16 val);
int jlsemi_fetch_bit(struct phy_device *phydev,
int page, u32 regnum, u16 val);
int jlsemi_drivers_register(struct phy_driver *phydrvs, int size);
void jlsemi_drivers_unregister(struct phy_driver *phydrvs, int size);
/**
* module_jlsemi_driver() - Helper macro for registering PHY drivers
* @__phy_drivers: array of PHY drivers to register
*
* Helper macro for PHY drivers which do not do anything special in module
* init/exit. Each module may only use this macro once, and calling it
* replaces module_init() and module_exit().
*/
#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE)
#define jlsemi_module_driver(__phy_drivers, __count) \
static int __init phy_module_init(void) \
{ \
return jlsemi_drivers_register(__phy_drivers, __count); \
} \
module_init(phy_module_init); \
static void __exit phy_module_exit(void) \
{ \
jlsemi_drivers_unregister(__phy_drivers, __count); \
} \
module_exit(phy_module_exit)
#define module_jlsemi_driver(__phy_drivers) \
jlsemi_module_driver(__phy_drivers, ARRAY_SIZE(__phy_drivers))
#else
#define module_jlsemi_driver(__phy_drivers) \
module_phy_driver(__phy_drivers)
#endif
#endif /* _JLSEMI_CORE_H */

View File

@ -0,0 +1,341 @@
/* SPDX-License-Identifier: GPL-2.0
*
* Device Tree constants for JLSemi PHY
*
* Author: Gangqiao Kuang
*
* Copyright (c) 2021 JLSemi Corporation
*/
#ifndef _DT_BINDINGS_JLSEMI_PHY_H
#define _DT_BINDINGS_JLSEMI_PHY_H
/**************************** Linux Version Compatible ********************/
#define JLSEMI_DEV_COMPATIBLE (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE)
#define JL2XXX_GET_STRING (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE)
#define JL2XXX_GET_STAT (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE)
#define JL2XXX_PHY_TUNABLE (KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE)
#define JLSEMI_PHY_WOL (KERNEL_VERSION(3, 10, 0) < LINUX_VERSION_CODE)
/*************************************************************************/
/**************************** JLSemi Debug *******************************/
#define JLSEMI_DEBUG_INFO 0
/*************************************************************************/
/************************* JLSemi Phy Init Reentrant *********************/
#define JLSEMI_PHY_NOT_REENTRANT false
/*************************************************************************/
/**************************** JL1XXX-LED *********************************/
/* PHY LED Modes Select */
#define JL1XXX_LED0_STRAP (1 << 0)
#define JL1XXX_LED0_EEE (1 << 1)
#define JL1XXX_LED0_100_ACTIVITY (1 << 2)
#define JL1XXX_LED0_10_ACTIVITY (1 << 3)
#define JL1XXX_LED0_100_LINK (1 << 4)
#define JL1XXX_LED0_10_LINK (1 << 5)
#define JL1XXX_LED1_STRAP (1 << 8)
#define JL1XXX_LED1_EEE (1 << 9)
#define JL1XXX_LED1_100_ACTIVITY (1 << 10)
#define JL1XXX_LED1_10_ACTIVITY (1 << 11)
#define JL1XXX_LED1_100_LINK (1 << 12)
#define JL1XXX_LED1_10_LINK (1 << 13)
/* PHY LED As Gpio Output Select */
#define JL1XXX_GPIO_LED0_OUT (1 << 2)
#define JL1XXX_GPIO_LED1_OUT (1 << 3)
#define JL1XXX_GPIO_LED0_EN (1 << 14)
#define JL1XXX_GPIO_LED1_EN (1 << 15)
/* PHY LED Control Enable Mask Select */
#define JL1XXX_LED_STATIC_OP_EN (1 << 0)
#define JL1XXX_LED_MODE_EN (1 << 1)
#define JL1XXX_LED_GLOABL_PERIOD_EN (1 << 2)
#define JL1XXX_LED_GLOBAL_ON_EN (1 << 3)
#define JL1XXX_LED_GPIO_OUT_EN (1 << 4)
//-----------------------------------------------------------------------//
/* PHY LED Control Enable Mask Config */
#define JL1XXX_LED_CTRL_EN (0)
/* PHY LED Modes Config */
#define JL1XXX_CFG_LED_MODE (JL1XXX_LED0_100_LINK | \
JL1XXX_LED0_10_LINK | \
JL1XXX_LED1_100_ACTIVITY | \
JL1XXX_LED1_10_ACTIVITY)
/* PHY LED As Gpio Output Config */
#define JL1XXX_CFG_GPIO (JL1XXX_GPIO_LED0_EN | \
JL1XXX_GPIO_LED0_OUT | \
JL1XXX_GPIO_LED1_EN | \
JL1XXX_GPIO_LED1_OUT)
/* PHY LED Global Period Config */
#define JL1XXX_GLOBAL_PERIOD_MS 0x10
/* PHY LED Global Hold On Config */
#define JL1XXX_GLOBAL_ON_MS 0x8
/**************************************************************************/
/****************************** JL1XXX-WOL ********************************/
/* PHY WOL Control Enable Mask Select */
#define JL1XXX_WOL_STATIC_OP_EN (1 << 0)
//-----------------------------------------------------------------------//
/* PHY WOL Control Enable Mask Config */
#define JL1XXX_WOL_CTRL_EN (0)
/*************************************************************************/
/***************************** JL1XXX-INTR *******************************/
/* PHY Interrupt Control Enable Mask Select */
#define JL1XXX_INTR_STATIC_OP_EN (1 << 0)
#define JL1XXX_INTR_LINK_CHANGE_EN (1 << 1)
#define JL1XXX_INTR_AN_ERR_EN (1 << 2)
//-----------------------------------------------------------------------//
/* PHY Interrupt Irq Number Config */
#define JL1XXX_INTR_IRQ -1
/* PHY Interrupt Control Enable Mask Config */
#define JL1XXX_INTR_CTRL_EN (0)
/*************************************************************************/
/**************************** JL1XXX-MDI *********************************/
/* PHY MDI Control Mode Enable Mask Select */
#define JL1XXX_MDI_STATIC_OP_EN (1 << 0)
#define JL1XXX_MDI_RATE_EN (1 << 1)
#define JL1XXX_MDI_AMPLITUDE_EN (1 << 2)
/* PHY MDI Rate Select */
#define JL1XXX_MDI_RATE_STANDARD 0
#define JL1XXX_MDI_RATE_ACCELERATE 1
/* PHY MDI Amplitude Select */
#define JL1XXX_MDI_AMPLITUDE0 0
#define JL1XXX_MDI_AMPLITUDE1 1
#define JL1XXX_MDI_AMPLITUDE2 2
#define JL1XXX_MDI_AMPLITUDE3 3
#define JL1XXX_MDI_AMPLITUDE4 4
#define JL1XXX_MDI_AMPLITUDE5 5
#define JL1XXX_MDI_AMPLITUDE6 6
#define JL1XXX_MDI_AMPLITUDE7 7
//-----------------------------------------------------------------------//
/* PHY MDI Control Mode Enable Mask Config */
#define JL1XXX_MDI_CTRL_EN (0)
/* PHY MDI Rate Config */
#define JL1XXX_MDI_RATE JL1XXX_MDI_RATE_ACCELERATE
/* PHY MDI Amplitude Config */
#define JL1XXX_MDI_AMPLITUDE JL1XXX_MDI_AMPLITUDE4
/*************************************************************************/
/**************************** JL1XXX-RMII ********************************/
/* PHY RMII Control Mode Enable Mask Select */
#define JL1XXX_RMII_STATIC_OP_EN (1 << 0)
#define JL1XXX_RMII_MODE_EN (1 << 1)
#define JL1XXX_RMII_CLK_50M_INPUT_EN (1 << 2)
#define JL1XXX_RMII_TX_SKEW_EN (1 << 3)
#define JL1XXX_RMII_RX_SKEW_EN (1 << 4)
#define JL1XXX_RMII_CRS_DV_EN (1 << 5)
//-----------------------------------------------------------------------//
/* PHY RMII Control Mode Enable Mask Config */
#define JL1XXX_RMII_CTRL_EN (0)
/* PHY RMII Timing Config */
#define JL1XXX_RMII_TX_TIMING 0xf
#define JL1XXX_RMII_RX_TIMING 0xf
/*************************************************************************/
/**************************** JL2XXX-LED *********************************/
/* PHY LED Modes Select*/
#define JL2XXX_LED0_LINK10 (1 << 0)
#define JL2XXX_LED0_LINK100 (1 << 1)
#define JL2XXX_LED0_LINK1000 (1 << 3)
#define JL2XXX_LED0_ACTIVITY (1 << 4)
#define JL2XXX_LED1_LINK10 (1 << 5)
#define JL2XXX_LED1_LINK100 (1 << 6)
#define JL2XXX_LED1_LINK1000 (1 << 8)
#define JL2XXX_LED1_ACTIVITY (1 << 9)
#define JL2XXX_LED2_LINK10 (1 << 10)
#define JL2XXX_LED2_LINK100 (1 << 11)
#define JL2XXX_LED2_LINK1000 (1 << 13)
#define JL2XXX_LED2_ACTIVITY (1 << 14)
/* mode_A = 0 and mode_B = 1 default mode_A */
#define JL2XXX_LED_GLB_MODE_B (1 << 15)
/* PHY LED Polarity Select */
#define JL2XXX_LED0_POLARITY (1 << 12)
#define JL2XXX_LED1_POLARITY (1 << 11)
#define JL2XXX_LED2_POLARITY (1 << 10)
/* PHY LED Control Enable Mask Select */
#define JL2XXX_LED_STATIC_OP_EN (1 << 0)
#define JL2XXX_LED_MODE_EN (1 << 1)
#define JL2XXX_LED_GLOABL_PERIOD_EN (1 << 2)
#define JL2XXX_LED_GLOBAL_ON_EN (1 << 3)
#define JL2XXX_LED_POLARITY_EN (1 << 4)
//-----------------------------------------------------------------------//
/* PHY LED Control Enable Mask Config */
#define JL2XXX_LED_CTRL_EN (0)
/* PHY LED Modes Config */
#define JL2XXX_CFG_LED_MODE (JL2XXX_LED0_LINK10 | \
JL2XXX_LED0_ACTIVITY | \
JL2XXX_LED1_LINK100 | \
JL2XXX_LED1_ACTIVITY | \
JL2XXX_LED2_LINK1000 | \
JL2XXX_LED2_ACTIVITY)
/* PHY LED Polarity Config */
#define JL2XXX_LED_POLARITY (JL2XXX_LED0_POLARITY | \
JL2XXX_LED1_POLARITY | \
JL2XXX_LED2_POLARITY)
/* PHY LED Global Period Config */
#define JL2XXX_GLOBAL_PERIOD_MS 0x3
/* PHY LED Global Hold On Config */
#define JL2XXX_GLOBAL_ON_MS 0x2
/*************************************************************************/
/**************************** JL2XXX-FLD *********************************/
/* PHY Fast Link Down Control Enable Mask Select */
#define JL2XXX_FLD_STATIC_OP_EN (1 << 0)
//-----------------------------------------------------------------------//
/* PHY Fast Link Down Control Enable Mask Config */
#define JL2XXX_FLD_CTRL_EN (0)
/* PHY Fast Link Down Delay Config */
#define JL2XXX_FLD_DELAY 0
/*************************************************************************/
/**************************** JL2XXX-WOL *********************************/
/* PHY WOL Control Enable Mask Select */
#define JL2XXX_WOL_STATIC_OP_EN (1 << 0)
//-----------------------------------------------------------------------//
/* PHY WOL Control Enable Mask Config */
#define JL2XXX_WOL_CTRL_EN (0)
/*************************************************************************/
/**************************** JL2XXX-INTR ********************************/
/* PHY Interrupt Control Enable Mask Select */
#define JL2XXX_INTR_STATIC_OP_EN (1 << 0)
#define JL2XXX_INTR_LINK_CHANGE_EN (1 << 1)
#define JL2XXX_INTR_AN_ERR_EN (1 << 2)
#define JL2XXX_INTR_AN_COMPLETE_EN (1 << 3)
#define JL2XXX_INTR_AN_PAGE_RECE (1 << 4)
//-----------------------------------------------------------------------//
/* PHY Interrupt Irq Number Config */
#define JL2XXX_INTR_IRQ -1
/* PHY Interrupt Control Enable Mask Config */
#define JL2XXX_INTR_CTRL_EN (0)
/*************************************************************************/
/**************************** JL2XXX-DSFT ********************************/
/* PHY Downshift Control Enable Mask */
#define JL2XXX_DSFT_STATIC_OP_EN (1 << 0)
//-----------------------------------------------------------------------//
/* PHY Downshift Control Enable Config */
#define JL2XXX_DSFT_CTRL_EN (0)
/* PHY Downshift Count Config */
#define JL2XXX_DSFT_AN_CNT 4
/*************************************************************************/
/**************************** JL2XXX-RGMII *******************************/
/* PHY RGMII Control Mode Enable Mask Select */
#define JL2XXX_RGMII_STATIC_OP_EN (1 << 0)
#define JL2XXX_RGMII_TX_DLY_EN (1 << 1)
#define JL2XXX_RGMII_RX_DLY_EN (1 << 2)
/* PHY RGMII DELAY BIT */
#define JL2XXX_RGMII_TX_DLY_2NS (1 << 8)
#define JL2XXX_RGMII_RX_DLY_2NS (1 << 9)
//-----------------------------------------------------------------------//
/* PHY RGMII Control Mode Enable Mask Config */
#define JL2XXX_RGMII_CTRL_EN (0)
/*************************************************************************/
/**************************** JL2XXX-PATCH *******************************/
/* PHY Patch Control Mode Enable Mask Select */
#define JL2XXX_PATCH_STATIC_OP_EN (1 << 0)
//-----------------------------------------------------------------------//
/* PHY Patch Control Mode Enable Mask Config */
#define JL2XXX_PATCH_CTRL_EN (JL2XXX_PATCH_STATIC_OP_EN)
/*************************************************************************/
/**************************** JL2XXX-CLOCK *******************************/
/* PHY Clock Control Mode Enable Mask Select */
#define JL2XXX_CLK_STATIC_OP_EN (1 << 0)
#define JL2XXX_25M_CLK_OUT_EN (1 << 1)
#define JL2XXX_125M_CLK_OUT_EN (1 << 2)
#define JL2XXX_CLK_OUT_DIS (1 << 3)
//-----------------------------------------------------------------------//
/* PHY Clock Control Mode Enable Mask Config */
#define JL2XXX_CLK_CTRL_EN (0)
/*************************************************************************/
/**************************** JL2XXX-WORK_MODE ***************************/
/* PHY Work Mode Control Mode Enable Mask Select */
#define JL2XXX_WORK_MODE_STATIC_OP_EN (1 << 0)
/* PHY Work Mode Select */
#define JL2XXX_UTP_RGMII_MODE 0
#define JL2XXX_FIBER_RGMII_MODE 1
#define JL2XXX_UTP_FIBER_RGMII_MODE 2
#define JL2XXX_UTP_SGMII_MODE 3
#define JL2XXX_PHY_SGMII_RGMII_MODE 4
#define JL2XXX_MAC_SGMII_RGMII_MODE 5
#define JL2XXX_UTP_FIBER_FORCE_MODE1 6
#define JL2XXX_UTP_FIBER_FORCE_MODE2 7
//-----------------------------------------------------------------------//
/* PHY Work Mode Control Mode Enable Mask Config */
#define JL2XXX_WORK_MODE_CTRL_EN (0)
/* PHY Work Mode Config */
#define JL2XXX_WORK_MODE_MODE JL2XXX_UTP_RGMII_MODE
/*************************************************************************/
/**************************** JL2XXX-LOOPBACK ****************************/
/* PHY Loopback Control Mode Enable Mask Select */
#define JL2XXX_LPBK_STATIC_OP_EN (1 << 0)
/* PHY Loopback Mode Select */
#define JL2XXX_LPBK_PCS_10M 0
#define JL2XXX_LPBK_PCS_100M 1
#define JL2XXX_LPBK_PCS_1000M 2
#define JL2XXX_LPBK_PMD_1000M 3
#define JL2XXX_LPBK_EXT_STUB_1000M 4
//-----------------------------------------------------------------------//
/* PHY Loopback Control Mode Enable Mask Config */
#define JL2XXX_LPBK_CTRL_EN (0)
/* PHY Loopback Mode Config */
#define JL2XXX_LPBK_MODE JL2XXX_LPBK_PCS_1000M
/*************************************************************************/
/**************************** JL2XXX-SLEW_RATE ****************************/
/* PHY Slew Rate Control Mode Enable Mask Select */
#define JL2XXX_SLEW_RATE_STATIC_OP_EN (1 << 0)
//-----------------------------------------------------------------------//
/* PHY Slew Rate Control Mode Enable Mask Config */
#define JL2XXX_SLEW_RATE_CTRL_EN (0)
/*************************************************************************/
/**************************** JL2XXX-RXC_OUT *****************************/
/* PHY Rx Clock Out Control Mode Enable Mask Select */
#define JL2XXX_RXC_OUT_STATIC_OP_EN (1 << 0)
//-----------------------------------------------------------------------//
/* PHY Rx Clock Out Control Mode Enable Mask Config */
#define JL2XXX_RXC_OUT_CTRL_EN (0)
/*************************************************************************/
#endif

577
drivers/net/phy/jlsemi.c Normal file
View File

@ -0,0 +1,577 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/jlsemi.c
*
* Driver for JLSemi PHYs
*
* Author: Gangqiao Kuang <gqkuang@jlsemi.com>
*
* Copyright (c) 2021 JingLue Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include "jlsemi-core.h"
#include <linux/phy.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#define DRIVER_VERSION "1.2.9"
#define DRIVER_NAME_100M "JL1xxx Fast Ethernet " DRIVER_VERSION
#define DRIVER_NAME_1000M "JL2xxx Gigabit Ethernet " DRIVER_VERSION
MODULE_DESCRIPTION("JLSemi PHY driver");
MODULE_AUTHOR("Gangqiao Kuang");
MODULE_LICENSE("GPL");
#if (JLSEMI_DEBUG_INFO)
static int jlsemi_phy_reg_print(struct phy_device *phydev)
{
int ret;
int i;
for (i = 0; i < ARRAY_SIZE(jl_phy); i++) {
if (jl_phy[i].enable) {
ret = jlsemi_read_paged(phydev, jl_phy[i].page,
jl_phy[i].reg);
JLSEMI_PHY_MSG("%s: 0x%x\n", jl_phy[i].string, ret);
if (ret < 0)
return ret;
}
}
return 0;
}
#endif
static int jl1xxx_probe(struct phy_device *phydev)
{
struct device *dev = jlsemi_get_mdio(phydev);
struct jl1xxx_priv *jl1xxx = NULL;
int err;
jl1xxx = devm_kzalloc(dev, sizeof(*jl1xxx), GFP_KERNEL);
if (!jl1xxx)
return -ENOMEM;
phydev->priv = jl1xxx;
#if (JLSEMI_KERNEL_DEVICE_TREE_USE)
if (!dev->of_node)
JLSEMI_PHY_MSG("%s: Find device node failed\n", __func__);
#endif
err = jl1xxx_operation_args_get(phydev);
if (err < 0)
return err;
if (jl1xxx->intr.enable & JL1XXX_INTR_STATIC_OP_EN)
phydev->irq = JL1XXX_INTR_IRQ;
jl1xxx->static_inited = false;
return 0;
}
static int jl1xxx_config_init(struct phy_device *phydev)
{
struct jl1xxx_priv *priv = phydev->priv;
int ret;
if (!priv->static_inited) {
#if (JLSEMI_DEBUG_INFO)
JLSEMI_PHY_MSG("jl1xxx_config_init_before:\n");
ret = jlsemi_phy_reg_print(phydev);
if (ret < 0)
return ret;
#endif
ret = jl1xxx_static_op_init(phydev);
if (ret < 0)
return ret;
#if (JLSEMI_DEBUG_INFO)
JLSEMI_PHY_MSG("jl1xxx_config_init_after:\n");
ret = jlsemi_phy_reg_print(phydev);
if (ret < 0)
return ret;
#endif
priv->static_inited = JLSEMI_PHY_NOT_REENTRANT;
}
return 0;
}
static int jl1xxx_ack_interrupt(struct phy_device *phydev)
{
int err;
err = jl1xxx_intr_ack_event(phydev);
if (err < 0)
return err;
return 0;
}
static int jl1xxx_config_intr(struct phy_device *phydev)
{
struct jl1xxx_priv *priv = phydev->priv;
int err;
if (priv->intr.enable & JL1XXX_INTR_STATIC_OP_EN) {
err = jl1xxx_ack_interrupt(phydev);
if (err < 0)
return err;
err = jl1xxx_intr_static_op_set(phydev);
if (err < 0)
return err;
}
return 0;
}
static int jl1xxx_read_status(struct phy_device *phydev)
{
struct jl1xxx_priv *priv = phydev->priv;
int err;
if (priv->intr.enable & JL1XXX_INTR_STATIC_OP_EN) {
err = jl1xxx_ack_interrupt(phydev);
if (err < 0)
return err;
}
return genphy_read_status(phydev);
}
static void jl1xxx_remove(struct phy_device *phydev)
{
struct device *dev = jlsemi_get_mdio(phydev);
struct jl1xxx_priv *priv = phydev->priv;
if (priv)
devm_kfree(dev, priv);
}
#if (JLSEMI_PHY_WOL)
static void jl1xxx_get_wol(struct phy_device *phydev,
struct ethtool_wolinfo *wol)
{
struct jl1xxx_priv *priv = phydev->priv;
int wol_en;
if (priv->wol.ethtool) {
wol->supported = WAKE_MAGIC;
wol->wolopts = 0;
wol_en = jl1xxx_wol_dynamic_op_get(phydev);
if (!wol_en)
wol->wolopts |= WAKE_MAGIC;
}
}
static int jl1xxx_set_wol(struct phy_device *phydev,
struct ethtool_wolinfo *wol)
{
struct jl1xxx_priv *priv = phydev->priv;
int err;
if (priv->wol.ethtool) {
if (wol->wolopts & WAKE_MAGIC) {
err = jl1xxx_wol_dynamic_op_set(phydev);
if (err < 0)
return err;
}
}
return 0;
}
#endif
static int jl1xxx_suspend(struct phy_device *phydev)
{
return genphy_suspend(phydev);
}
static int jl1xxx_resume(struct phy_device *phydev)
{
return genphy_resume(phydev);
}
static int jl2xxx_probe(struct phy_device *phydev)
{
struct device *dev = jlsemi_get_mdio(phydev);
struct jl2xxx_priv *jl2xxx = NULL;
int err;
jl2xxx = devm_kzalloc(dev, sizeof(*jl2xxx), GFP_KERNEL);
if (!jl2xxx)
return -ENOMEM;
phydev->priv = jl2xxx;
#if (JLSEMI_KERNEL_DEVICE_TREE_USE)
if (!dev->of_node)
JLSEMI_PHY_MSG("%s: Find device node failed\n", __func__);
#endif
err = jl2xxx_operation_args_get(phydev);
if (err < 0)
return err;
if (jl2xxx->intr.enable & JL2XXX_INTR_STATIC_OP_EN)
phydev->irq = JL2XXX_INTR_IRQ;
jl2xxx->static_inited = false;
jl2xxx->nstats = ARRAY_SIZE(jl2xxx_hw_stats);
jl2xxx->hw_stats = jl2xxx_hw_stats;
jl2xxx->stats = kcalloc(jl2xxx->nstats, sizeof(u64), GFP_KERNEL);
if (!jl2xxx->stats)
return -ENOMEM;
return 0;
}
static int jl2xxx_config_init(struct phy_device *phydev)
{
struct jl2xxx_priv *priv = phydev->priv;
int ret;
if (!priv->static_inited) {
#if (JLSEMI_DEBUG_INFO)
JLSEMI_PHY_MSG("jl2xxx_config_init_before:\n");
ret = jlsemi_phy_reg_print(phydev);
if (ret < 0)
return ret;
#endif
ret = jl2xxx_static_op_init(phydev);
if (ret < 0)
return ret;
#if (JLSEMI_DEBUG_INFO)
JLSEMI_PHY_MSG("jl2xxx_config_init_after:\n");
ret = jlsemi_phy_reg_print(phydev);
if (ret < 0)
return ret;
#endif
priv->static_inited = JLSEMI_PHY_NOT_REENTRANT;
}
return 0;
}
static int jl2xxx_ack_interrupt(struct phy_device *phydev)
{
int err;
err = jl2xxx_intr_ack_event(phydev);
if (err < 0)
return err;
return 0;
}
static int jl2xxx_config_intr(struct phy_device *phydev)
{
struct jl2xxx_priv *priv = phydev->priv;
int err;
if (priv->intr.enable & JL2XXX_INTR_STATIC_OP_EN) {
err = jl2xxx_ack_interrupt(phydev);
if (err < 0)
return err;
err = jl2xxx_intr_static_op_set(phydev);
if (err < 0)
return err;
}
return 0;
}
static int jl2xxx_read_status(struct phy_device *phydev)
{
struct jl2xxx_priv *priv = phydev->priv;
bool fiber_mode;
int err;
if (priv->intr.enable & JL2XXX_INTR_STATIC_OP_EN) {
err = jl2xxx_ack_interrupt(phydev);
if (err < 0)
return err;
}
fiber_mode = jl2xxx_read_fiber_status(phydev);
if (fiber_mode)
return 0;
return genphy_read_status(phydev);
}
static int jl1xxx_config_aneg(struct phy_device *phydev)
{
return genphy_config_aneg(phydev);
}
static int jl2xxx_config_aneg(struct phy_device *phydev)
{
u16 phy_mode;
int val;
val = jlsemi_read_paged(phydev, JL2XXX_PAGE18,
JL2XXX_WORK_MODE_REG);
phy_mode = val & JL2XXX_WORK_MODE_MASK;
if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
return 0;
if ((phydev->interface != PHY_INTERFACE_MODE_SGMII) &&
((phy_mode == JL2XXX_FIBER_RGMII_MODE) ||
(phy_mode == JL2XXX_UTP_FIBER_RGMII_MODE)))
return jl2xxx_config_aneg_fiber(phydev);
return genphy_config_aneg(phydev);
}
static int jl2xxx_suspend(struct phy_device *phydev)
{
return genphy_suspend(phydev);
}
static int jl2xxx_resume(struct phy_device *phydev)
{
return genphy_resume(phydev);
}
#if (JLSEMI_PHY_WOL)
static void jl2xxx_get_wol(struct phy_device *phydev,
struct ethtool_wolinfo *wol)
{
struct jl2xxx_priv *priv = phydev->priv;
int wol_en;
if (priv->wol.ethtool) {
wol->supported = WAKE_MAGIC;
wol->wolopts = 0;
wol_en = jl2xxx_wol_dynamic_op_get(phydev);
if (wol_en)
wol->wolopts |= WAKE_MAGIC;
}
}
static int jl2xxx_set_wol(struct phy_device *phydev,
struct ethtool_wolinfo *wol)
{
struct jl2xxx_priv *priv = phydev->priv;
int err;
if (priv->wol.ethtool) {
if (wol->wolopts & WAKE_MAGIC) {
err = jl2xxx_wol_dynamic_op_set(phydev);
if (err < 0)
return err;
}
}
return 0;
}
#endif
#if (JL2XXX_PHY_TUNABLE)
static int jl2xxx_get_tunable(struct phy_device *phydev,
struct ethtool_tunable *tuna, void *data)
{
struct jl2xxx_priv *priv = phydev->priv;
switch (tuna->id) {
case ETHTOOL_PHY_FAST_LINK_DOWN:
if (priv->fld.ethtool)
return jl2xxx_fld_dynamic_op_get(phydev, data);
else
return 0;
case ETHTOOL_PHY_DOWNSHIFT:
if (priv->downshift.ethtool)
return jl2xxx_downshift_dynamic_op_get(phydev, data);
else
return 0;
default:
return -EOPNOTSUPP;
}
return 0;
}
static int jl2xxx_set_tunable(struct phy_device *phydev,
struct ethtool_tunable *tuna, const void *data)
{
struct jl2xxx_priv *priv = phydev->priv;
switch (tuna->id) {
case ETHTOOL_PHY_FAST_LINK_DOWN:
if (priv->fld.ethtool)
return jl2xxx_fld_dynamic_op_set(phydev, data);
else
return 0;
case ETHTOOL_PHY_DOWNSHIFT:
if (priv->downshift.ethtool)
return jl2xxx_downshift_dynamic_op_set(phydev,
*(const u8 *)data);
else
return 0;
default:
return -EOPNOTSUPP;
}
return 0;
}
#endif
#if (JL2XXX_GET_STAT)
static u64 get_stat(struct phy_device *phydev, int i)
{
struct jl2xxx_priv *priv = phydev->priv;
int val;
val = jlsemi_read_paged(phydev, priv->hw_stats[i].page,
priv->hw_stats[i].reg);
if (val < 0)
return U64_MAX;
val = val & priv->hw_stats[i].mask;
priv->stats[i] += val;
return priv->stats[i];
}
static void jl2xxx_get_stats(struct phy_device *phydev,
struct ethtool_stats *stats, u64 *data)
{
struct jl2xxx_priv *priv = phydev->priv;
int i;
if (!priv)
return;
for (i = 0; i < priv->nstats; i++)
data[i] = get_stat(phydev, i);
}
#endif
#if (JL2XXX_GET_STRING)
static void jl2xxx_get_strings(struct phy_device *phydev, u8 *data)
{
struct jl2xxx_priv *priv = phydev->priv;
int i;
if (!priv)
return;
for (i = 0; i < priv->nstats; i++)
strlcpy(data + i * ETH_GSTRING_LEN,
priv->hw_stats[i].string, ETH_GSTRING_LEN);
}
#endif
static void jl2xxx_remove(struct phy_device *phydev)
{
struct device *dev = jlsemi_get_mdio(phydev);
struct jl2xxx_priv *priv = phydev->priv;
kfree(priv->stats);
if (priv)
devm_kfree(dev, priv);
}
static inline int jlsemi_aneg_done(struct phy_device *phydev)
{
int retval = phy_read(phydev, MII_BMSR);
return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
}
static int jl2xxx_aneg_done(struct phy_device *phydev)
{
u16 phy_mode;
int val;
val = jlsemi_read_paged(phydev, JL2XXX_PAGE18,
JL2XXX_WORK_MODE_REG);
phy_mode = val & JL2XXX_WORK_MODE_MASK;
if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
return 0;
// fiber not an complite
if ((phydev->interface != PHY_INTERFACE_MODE_SGMII) &&
((phy_mode == JL2XXX_FIBER_RGMII_MODE) ||
(phy_mode == JL2XXX_UTP_FIBER_RGMII_MODE)))
return BMSR_ANEGCOMPLETE;
return jlsemi_aneg_done(phydev);
}
static struct phy_driver jlsemi_drivers[] = {
{
.phy_id = JL1XXX_PHY_ID,
.phy_id_mask = JLSEMI_PHY_ID_MASK,
.name = DRIVER_NAME_100M,
/* PHY_BASIC_FEATURES */
.features = PHY_BASIC_FEATURES,
.probe = jl1xxx_probe,
.config_intr = jl1xxx_config_intr,
.read_status = jl1xxx_read_status,
.config_init = jl1xxx_config_init,
.config_aneg = jl1xxx_config_aneg,
.aneg_done = jlsemi_aneg_done,
.suspend = jl1xxx_suspend,
.resume = jl1xxx_resume,
.remove = jl1xxx_remove,
#if (JLSEMI_PHY_WOL)
.get_wol = jl1xxx_get_wol,
.set_wol = jl1xxx_set_wol,
#endif
},
{
.phy_id = JL2XXX_PHY_ID,
.phy_id_mask = JLSEMI_PHY_ID_MASK,
.name = DRIVER_NAME_1000M,
/* PHY_BASIC_FEATURES */
.features = PHY_GBIT_FEATURES,
.probe = jl2xxx_probe,
.config_intr = jl2xxx_config_intr,
.read_status = jl2xxx_read_status,
.config_init = jl2xxx_config_init,
.config_aneg = jl2xxx_config_aneg,
.aneg_done = jl2xxx_aneg_done,
.suspend = jl2xxx_suspend,
.resume = jl2xxx_resume,
.remove = jl2xxx_remove,
#if (JLSEMI_PHY_WOL)
.get_wol = jl2xxx_get_wol,
.set_wol = jl2xxx_set_wol,
#endif
#if (JL2XXX_PHY_TUNABLE)
.get_tunable = jl2xxx_get_tunable,
.set_tunable = jl2xxx_set_tunable,
#endif
#if (JL2XXX_GET_STAT)
.get_stats = jl2xxx_get_stats,
#endif
#if (JL2XXX_GET_STRING)
.get_strings = jl2xxx_get_strings,
#endif
},
};
module_jlsemi_driver(jlsemi_drivers);
static struct mdio_device_id __maybe_unused jlsemi_tbl[] = {
{JL1XXX_PHY_ID, JLSEMI_PHY_ID_MASK},
{JL2XXX_PHY_ID, JLSEMI_PHY_ID_MASK},
{ }
};
MODULE_DEVICE_TABLE(mdio, jlsemi_tbl);