162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2021 pureLiFi
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/kernel.h>
762306a36Sopenharmony_ci#include <linux/errno.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include "chip.h"
1062306a36Sopenharmony_ci#include "mac.h"
1162306a36Sopenharmony_ci#include "usb.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_civoid plfxlc_chip_init(struct plfxlc_chip *chip,
1462306a36Sopenharmony_ci		      struct ieee80211_hw *hw,
1562306a36Sopenharmony_ci		      struct usb_interface *intf)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	memset(chip, 0, sizeof(*chip));
1862306a36Sopenharmony_ci	mutex_init(&chip->mutex);
1962306a36Sopenharmony_ci	plfxlc_usb_init(&chip->usb, hw, intf);
2062306a36Sopenharmony_ci}
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_civoid plfxlc_chip_release(struct plfxlc_chip *chip)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	plfxlc_usb_release(&chip->usb);
2562306a36Sopenharmony_ci	mutex_destroy(&chip->mutex);
2662306a36Sopenharmony_ci}
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ciint plfxlc_set_beacon_interval(struct plfxlc_chip *chip, u16 interval,
2962306a36Sopenharmony_ci			       u8 dtim_period, int type)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	if (!interval ||
3262306a36Sopenharmony_ci	    (chip->beacon_set && chip->beacon_interval == interval))
3362306a36Sopenharmony_ci		return 0;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	chip->beacon_interval = interval;
3662306a36Sopenharmony_ci	chip->beacon_set = true;
3762306a36Sopenharmony_ci	return plfxlc_usb_wreq(chip->usb.ez_usb,
3862306a36Sopenharmony_ci			       &chip->beacon_interval,
3962306a36Sopenharmony_ci			       sizeof(chip->beacon_interval),
4062306a36Sopenharmony_ci			       USB_REQ_BEACON_INTERVAL_WR);
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ciint plfxlc_chip_init_hw(struct plfxlc_chip *chip)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	unsigned char *addr = plfxlc_mac_get_perm_addr(plfxlc_chip_to_mac(chip));
4662306a36Sopenharmony_ci	struct usb_device *udev = interface_to_usbdev(chip->usb.intf);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	pr_info("plfxlc chip %04x:%04x v%02x %pM %s\n",
4962306a36Sopenharmony_ci		le16_to_cpu(udev->descriptor.idVendor),
5062306a36Sopenharmony_ci		le16_to_cpu(udev->descriptor.idProduct),
5162306a36Sopenharmony_ci		le16_to_cpu(udev->descriptor.bcdDevice),
5262306a36Sopenharmony_ci		addr,
5362306a36Sopenharmony_ci		plfxlc_speed(udev->speed));
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	return plfxlc_set_beacon_interval(chip, 100, 0, 0);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ciint plfxlc_chip_switch_radio(struct plfxlc_chip *chip, u16 value)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	int r;
6162306a36Sopenharmony_ci	__le16 radio_on = cpu_to_le16(value);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	r = plfxlc_usb_wreq(chip->usb.ez_usb, &radio_on,
6462306a36Sopenharmony_ci			    sizeof(value), USB_REQ_POWER_WR);
6562306a36Sopenharmony_ci	if (r)
6662306a36Sopenharmony_ci		dev_err(plfxlc_chip_dev(chip), "POWER_WR failed (%d)\n", r);
6762306a36Sopenharmony_ci	return r;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ciint plfxlc_chip_enable_rxtx(struct plfxlc_chip *chip)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	plfxlc_usb_enable_tx(&chip->usb);
7362306a36Sopenharmony_ci	return plfxlc_usb_enable_rx(&chip->usb);
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_civoid plfxlc_chip_disable_rxtx(struct plfxlc_chip *chip)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	u8 value = 0;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	plfxlc_usb_wreq(chip->usb.ez_usb,
8162306a36Sopenharmony_ci			&value, sizeof(value), USB_REQ_RXTX_WR);
8262306a36Sopenharmony_ci	plfxlc_usb_disable_rx(&chip->usb);
8362306a36Sopenharmony_ci	plfxlc_usb_disable_tx(&chip->usb);
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ciint plfxlc_chip_set_rate(struct plfxlc_chip *chip, u8 rate)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	int r;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	if (!chip)
9162306a36Sopenharmony_ci		return -EINVAL;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	r = plfxlc_usb_wreq(chip->usb.ez_usb,
9462306a36Sopenharmony_ci			    &rate, sizeof(rate), USB_REQ_RATE_WR);
9562306a36Sopenharmony_ci	if (r)
9662306a36Sopenharmony_ci		dev_err(plfxlc_chip_dev(chip), "RATE_WR failed (%d)\n", r);
9762306a36Sopenharmony_ci	return r;
9862306a36Sopenharmony_ci}
99