162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * @File	cthardware.c
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * @Brief
862306a36Sopenharmony_ci * This file contains the implementation of hardware access methord.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * @Author	Liu Chun
1162306a36Sopenharmony_ci * @Date 	Jun 26 2008
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "cthardware.h"
1562306a36Sopenharmony_ci#include "cthw20k1.h"
1662306a36Sopenharmony_ci#include "cthw20k2.h"
1762306a36Sopenharmony_ci#include <linux/bug.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ciint create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type,
2062306a36Sopenharmony_ci		  enum CTCARDS model, struct hw **rhw)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	int err;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	switch (chip_type) {
2562306a36Sopenharmony_ci	case ATC20K1:
2662306a36Sopenharmony_ci		err = create_20k1_hw_obj(rhw);
2762306a36Sopenharmony_ci		break;
2862306a36Sopenharmony_ci	case ATC20K2:
2962306a36Sopenharmony_ci		err = create_20k2_hw_obj(rhw);
3062306a36Sopenharmony_ci		break;
3162306a36Sopenharmony_ci	default:
3262306a36Sopenharmony_ci		err = -ENODEV;
3362306a36Sopenharmony_ci		break;
3462306a36Sopenharmony_ci	}
3562306a36Sopenharmony_ci	if (err)
3662306a36Sopenharmony_ci		return err;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	(*rhw)->pci = pci;
3962306a36Sopenharmony_ci	(*rhw)->chip_type = chip_type;
4062306a36Sopenharmony_ci	(*rhw)->model = model;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	return 0;
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ciint destroy_hw_obj(struct hw *hw)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	int err;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	switch (hw->pci->device) {
5062306a36Sopenharmony_ci	case 0x0005:	/* 20k1 device */
5162306a36Sopenharmony_ci		err = destroy_20k1_hw_obj(hw);
5262306a36Sopenharmony_ci		break;
5362306a36Sopenharmony_ci	case 0x000B:	/* 20k2 device */
5462306a36Sopenharmony_ci		err = destroy_20k2_hw_obj(hw);
5562306a36Sopenharmony_ci		break;
5662306a36Sopenharmony_ci	default:
5762306a36Sopenharmony_ci		err = -ENODEV;
5862306a36Sopenharmony_ci		break;
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	return err;
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ciunsigned int get_field(unsigned int data, unsigned int field)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	int i;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	if (WARN_ON(!field))
6962306a36Sopenharmony_ci		return 0;
7062306a36Sopenharmony_ci	/* @field should always be greater than 0 */
7162306a36Sopenharmony_ci	for (i = 0; !(field & (1 << i)); )
7262306a36Sopenharmony_ci		i++;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	return (data & field) >> i;
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_civoid set_field(unsigned int *data, unsigned int field, unsigned int value)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	int i;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	if (WARN_ON(!field))
8262306a36Sopenharmony_ci		return;
8362306a36Sopenharmony_ci	/* @field should always be greater than 0 */
8462306a36Sopenharmony_ci	for (i = 0; !(field & (1 << i)); )
8562306a36Sopenharmony_ci		i++;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	*data = (*data & (~field)) | ((value << i) & field);
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
90