Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial USB2422 driver #14835

Merged
merged 12 commits into from
Oct 21, 2021
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 108 additions & 108 deletions tmk_core/protocol/arm_atsam/usb/usb2422.h → drivers/usb2422.c

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions drivers/usb2422.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* Copyright 2021 QMK
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include <stdbool.h>

#ifndef USB2422_ADDRESS
# define USB2422_ADDRESS 0x58
#endif

#ifndef USB2422_VENDOR_ID
# define USB2422_VENDOR_ID 0xFEED
#endif
#ifndef USB2422_PRODUCT_ID
# define USB2422_PRODUCT_ID 0x0001
#endif
#ifndef USB2422_DEVICE_VER
# define USB2422_DEVICE_VER 0x0001
#endif

#ifndef USB2422_MANUFACTURER
# define USB2422_MANUFACTURER "QMK"
#endif
#ifndef USB2422_PRODUCT
# define USB2422_PRODUCT "QMK Hub"
#endif

/** \brief Initialises the dependent subsystems */
void USB2422_init(void);

/** \brief Push configuration to the USB2422 device */
void USB2422_configure(void);

/** \brief Reset the chip (RESET_N)
*
* NOTE:
* Depends on a valid USB2422_RESET_PIN configuration
*/
void USB2422_reset(void);

/** \brief Indicates the USB state of the hub (SUSP_IND)
*
* NOTE:
* Depends on a valid USB2422_ACTIVE_PIN configuration
*/
bool USB2422_active(void);
2 changes: 1 addition & 1 deletion keyboards/massdrop/alt/alt.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "i2c_master.h"
#include "md_rgb_matrix.h" //For led keycodes
#include "usb/udi_cdc.h"
#include "usb/usb2422.h"
#include "usb/usb_hub.h"

#define LAYOUT_65_ansi_blocker( \
K01, K02, K03, K04, K05, K06, K07, K08, K09, K10, K11, K12, K13, K14, K15, \
Expand Down
9 changes: 9 additions & 0 deletions keyboards/massdrop/alt/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define DEBUG_BOOT_TRACING_PORT PB
#define DEBUG_BOOT_TRACING_PIN 23

/* USB2422 config */
#define USB2422_ADDRESS 0x58
#define USB2422_VENDOR_ID 0x04D8
#define USB2422_PRODUCT_ID 0xEEC5
#define USB2422_DEVICE_VER 0x0101
#define USB2422_MANUFACTURER "Massdrop Inc."
#define USB2422_PRODUCT "Massdrop Hub"
#define USB2422_ACTIVE_PIN A18

/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5

Expand Down
9 changes: 9 additions & 0 deletions keyboards/massdrop/ctrl/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define DEBUG_BOOT_TRACING_PORT PB
#define DEBUG_BOOT_TRACING_PIN 23

/* USB2422 config */
#define USB2422_ADDRESS 0x58
#define USB2422_VENDOR_ID 0x04D8
#define USB2422_PRODUCT_ID 0xEEC5
#define USB2422_DEVICE_VER 0x0101
#define USB2422_MANUFACTURER "Massdrop Inc."
#define USB2422_PRODUCT "Massdrop Hub"
#define USB2422_ACTIVE_PIN A18

/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5

Expand Down
2 changes: 1 addition & 1 deletion keyboards/massdrop/ctrl/ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "i2c_master.h"
#include "md_rgb_matrix.h" //For led keycodes
#include "usb/udi_cdc.h"
#include "usb/usb2422.h"
#include "usb/usb_hub.h"

#define LAYOUT( \
K01, K02, K03, K04, K05, K06, K07, K08, K09, K10, K11, K12, K13, K14, K15, \
Expand Down
4 changes: 3 additions & 1 deletion tmk_core/protocol/arm_atsam.mk
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ SRC += $(ARM_ATSAM_DIR)/usb/udi_hid.c
SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd.c
SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd_desc.c
SRC += $(ARM_ATSAM_DIR)/usb/ui.c
SRC += $(ARM_ATSAM_DIR)/usb/usb2422.c
SRC += $(ARM_ATSAM_DIR)/usb/usb.c
SRC += $(ARM_ATSAM_DIR)/usb/usb_device_udd.c
SRC += $(ARM_ATSAM_DIR)/usb/usb_hub.c
SRC += $(ARM_ATSAM_DIR)/usb/usb_util.c

SRC += $(DRIVER_PATH)/usb2422.c

# Search Path
VPATH += $(TMK_DIR)/$(ARM_ATSAM_DIR)
2 changes: 1 addition & 1 deletion tmk_core/protocol/arm_atsam/arm_atsam_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "i2c_master.h"
#include "spi.h"

#include "./usb/usb2422.h"
#include "./usb/usb_hub.h"

#ifndef MD_BOOTLOADER

Expand Down
19 changes: 19 additions & 0 deletions tmk_core/protocol/arm_atsam/i2c_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,4 +564,23 @@ uint8_t i2c_led_q_run(void) {

return 1;
}

__attribute__((weak)) void i2c_init(void) {
static bool is_initialised = false;
if (!is_initialised) {
is_initialised = true;

i2c0_init();
}
}

i2c_status_t i2c_transmit(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout) {
uint8_t ret = i2c0_transmit(address, (uint8_t *)data, length, timeout);
SERCOM0->I2CM.CTRLB.bit.CMD = 0x03;
while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) {
DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP);
}
return ret;
}

#endif // !defined(MD_BOOTLOADER) && defined(RGB_MATRIX_ENABLE)
6 changes: 6 additions & 0 deletions tmk_core/protocol/arm_atsam/i2c_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,10 @@ void i2c0_init(void);
uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout);
void i2c0_stop(void);

// Terrible interface compatiblity...
typedef int16_t i2c_status_t;

void i2c_init(void);
i2c_status_t i2c_transmit(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout);

#endif // _I2C_MASTER_H_
4 changes: 2 additions & 2 deletions tmk_core/protocol/arm_atsam/main_arm_atsam.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ int main(void) {

matrix_init();

USB2422_init();
USB_Hub_init();

DBGC(DC_MAIN_UDC_START_BEGIN);
udc_start();
Expand All @@ -306,7 +306,7 @@ int main(void) {
CDC_init();
DBGC(DC_MAIN_CDC_INIT_COMPLETE);

while (USB2422_Port_Detect_Init() == 0) {
while (USB_Hub_Port_Detect_Init() == 0) {
}

DBG_LED_OFF;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "arm_atsam_protocol.h"
#include "drivers/usb2422.h"
#include <string.h>

Usb2422 USB2422_shadow;
unsigned char i2c0_buf[34];

const uint16_t MFRNAME[] = {'M', 'a', 's', 's', 'd', 'r', 'o', 'p', ' ', 'I', 'n', 'c', '.'}; // Massdrop Inc.
const uint16_t PRDNAME[] = {'M', 'a', 's', 's', 'd', 'r', 'o', 'p', ' ', 'H', 'u', 'b'}; // Massdrop Hub
#ifndef MD_BOOTLOADER
// Serial number reported stops before first found space character or at last found character
const uint16_t SERNAME[] = {'U', 'n', 'a', 'v', 'a', 'i', 'l', 'a', 'b', 'l', 'e'}; // Unavailable
#else
// In production, this field is found, modified, and offset noted as the last 32-bit word in the bootloader space
// The offset allows the application to use the factory programmed serial (which may differ from the physical serial label)
// Serial number reported stops before first found space character or when max size is reached
__attribute__((__aligned__(4))) const uint16_t SERNAME[BOOTLOADER_SERIAL_MAX_SIZE] = {'M', 'D', 'H', 'U', 'B', 'B', 'O', 'O', 'T', 'L', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
// NOTE: Serial replacer will not write a string longer than given here as a precaution, so give enough
// space as needed and adjust BOOTLOADER_SERIAL_MAX_SIZE to match amount given
#endif // MD_BOOTLOADER

uint8_t usb_host_port;

#ifndef MD_BOOTLOADER
Expand All @@ -47,29 +31,7 @@ uint8_t usb_gcr_auto;

uint16_t adc_extra;

void USB_write2422_block(void) {
unsigned char *dest = i2c0_buf;
unsigned char *src;
unsigned char *base = (unsigned char *)&USB2422_shadow;

DBGC(DC_USB_WRITE2422_BLOCK_BEGIN);

for (src = base; src < base + 256; src += 32) {
dest[0] = src - base;
dest[1] = 32;
memcpy(&dest[2], src, 32);
i2c0_transmit(USB2422_ADDR, dest, 34, 50000);
SERCOM0->I2CM.CTRLB.bit.CMD = 0x03;
while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) {
DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP);
}
wait_us(100);
}

DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE);
}

void USB2422_init(void) {
void USB_Hub_init(void) {
Gclk * pgclk = GCLK;
Mclk * pmclk = MCLK;
Port * pport = PORT;
Expand Down Expand Up @@ -147,9 +109,7 @@ void USB2422_init(void) {
pusb->DEVICE.QOSCTRL.bit.DQOS = 2;
pusb->DEVICE.QOSCTRL.bit.CQOS = 2;

pport->Group[USB2422_HUB_ACTIVE_GROUP].PINCFG[USB2422_HUB_ACTIVE_PIN].bit.INEN = 1;

i2c0_init(); // IC2 clk must be high at USB2422 reset release time to signal SMB configuration
USB2422_init();

sr_exp_data.bit.HUB_CONNECT = 1; // connect signal
sr_exp_data.bit.HUB_RESET_N = 1; // reset high
Expand Down Expand Up @@ -181,62 +141,16 @@ void USB_reset(void) {
}

void USB_configure(void) {
Usb2422 *pusb2422 = &USB2422_shadow;
memset(pusb2422, 0, sizeof(Usb2422));

uint16_t *serial_use = (uint16_t *)SERNAME; // Default to use SERNAME from this file
uint8_t serial_length = sizeof(SERNAME) / sizeof(uint16_t); // Default to use SERNAME from this file
#ifndef MD_BOOTLOADER
uint32_t serial_ptrloc = (uint32_t)&_srom - 4;
#else // MD_BOOTLOADER
uint32_t serial_ptrloc = (uint32_t)&_erom - 4;
#endif // MD_BOOTLOADER
uint32_t serial_address = *(uint32_t *)serial_ptrloc; // Address of bootloader's serial number if available

DBGC(DC_USB_CONFIGURE_BEGIN);

if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc) // Check for factory programmed serial address
{
if ((serial_address & 0xFF) % 4 == 0) // Check alignment
{
serial_use = (uint16_t *)(serial_address);
serial_length = 0;
while ((*(serial_use + serial_length) > 32 && *(serial_use + serial_length) < 127) && serial_length < BOOTLOADER_SERIAL_MAX_SIZE) {
serial_length++;
DBGC(DC_USB_CONFIGURE_GET_SERIAL);
}
}
}

// configure Usb2422 registers
pusb2422->VID.reg = 0x04D8; // from Microchip 4/19/2018
pusb2422->PID.reg = 0xEEC5; // from Microchip 4/19/2018 = Massdrop, Inc. USB Hub
pusb2422->DID.reg = 0x0101; // BCD 01.01
pusb2422->CFG1.bit.SELF_BUS_PWR = 1; // self powered for now
pusb2422->CFG1.bit.HS_DISABLE = 1; // full or high speed
// pusb2422->CFG2.bit.COMPOUND = 0; // compound device
pusb2422->CFG3.bit.STRING_EN = 1; // strings enabled
// pusb2422->NRD.bit.PORT2_NR = 0; // MCU is non-removable
pusb2422->MAXPB.reg = 20; // 0mA
pusb2422->HCMCB.reg = 20; // 0mA
pusb2422->MFRSL.reg = sizeof(MFRNAME) / sizeof(uint16_t);
pusb2422->PRDSL.reg = sizeof(PRDNAME) / sizeof(uint16_t);
pusb2422->SERSL.reg = serial_length;
memcpy(pusb2422->MFRSTR, MFRNAME, sizeof(MFRNAME));
memcpy(pusb2422->PRDSTR, PRDNAME, sizeof(PRDNAME));
memcpy(pusb2422->SERSTR, serial_use, serial_length * sizeof(uint16_t));
// pusb2422->BOOSTUP.bit.BOOST=3; //upstream port
// pusb2422->BOOSTDOWN.bit.BOOST1=0; // extra port
// pusb2422->BOOSTDOWN.bit.BOOST2=2; //MCU is close
pusb2422->STCD.bit.USB_ATTACH = 1;
USB_write2422_block();
USB2422_configure();

adc_extra = 0;

DBGC(DC_USB_CONFIGURE_COMPLETE);
}

uint16_t USB_active(void) { return (PORT->Group[USB2422_HUB_ACTIVE_GROUP].IN.reg & (1 << USB2422_HUB_ACTIVE_PIN)) != 0; }
uint16_t USB_active(void) { return USB2422_active(); }

void USB_set_host_by_voltage(void) {
// UP is upstream device (HOST)
Expand Down Expand Up @@ -314,7 +228,7 @@ void USB_set_host_by_voltage(void) {
DBGC(DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE);
}

uint8_t USB2422_Port_Detect_Init(void) {
uint8_t USB_Hub_Port_Detect_Init(void) {
uint32_t port_detect_retry_ms;
uint32_t tmod;

Expand Down
51 changes: 51 additions & 0 deletions tmk_core/protocol/arm_atsam/usb/usb_hub.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright 2018 Massdrop 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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _USB2422_H_
#define _USB2422_H_

#define REV_USB2422 0x100

#define PORT_DETECT_RETRY_INTERVAL 2000

#define USB_EXTRA_ADC_THRESHOLD 900

#define USB_EXTRA_STATE_DISABLED 0
#define USB_EXTRA_STATE_ENABLED 1
#define USB_EXTRA_STATE_UNKNOWN 2
#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3

#define USB_HOST_PORT_1 0
#define USB_HOST_PORT_2 1
#define USB_HOST_PORT_UNKNOWN 2

extern uint8_t usb_host_port;
extern uint8_t usb_extra_state;
extern uint8_t usb_extra_manual;
extern uint8_t usb_gcr_auto;

void USB_Hub_init(void);
uint8_t USB_Hub_Port_Detect_Init(void);
void USB_reset(void);
void USB_configure(void);
uint16_t USB_active(void);
void USB_set_host_by_voltage(void);
uint16_t adc_get(uint8_t muxpos);
void USB_HandleExtraDevice(void);
void USB_ExtraSetState(uint8_t state);

#endif //_USB2422_H_